JSFiddle - React, Tailwind, and code Playground

by phloe

HTML

<div>
	<div style="width: 554px;">
		<h2>XXS</h2>
	</div>
	<div style="width: 768px;">
		<h2>XS</h2>
	</div>
	<div style="width: 1024px;">
		<h2>SM</h2>
	</div>
	<div style="width: 1160px;">
		<h2>MD</h2>
	</div>
	<div style="width: 1440px;">
		<h2>LG</h2>
	</div>
	<div style="width: 100%;">
		<h2>XL</h2>
	</div>
</div>

CSS

* {
	padding: 0;
	margin: 0;
}

html, body {
	height: 100%;
}
body {
	overflow: hidden;
}
div {
	position: absolute;
	top: 0;
	left: 0;
	height: 100%;
	background-color: rgba(255, 0, 0, 0.1);
}
h2 {
	text-align: right;
}

JavaScript

// global

var bps = [
	{
		bp: "xxs",
		max: 554
	},
	{
		bp: "xs",
		max: 768
	},
	{
		bp: "sm",
		max: 1024
	},
	{
		bp: "md",
		max: 1160
	},
	{
		bp: "lg",
		max: 1440
	},
	{
		bp: "xl",
		max: null
	}
];

var breakpoints = bps.map(({ bp }) => bp);
var min;
var bpSizes = bps.reduce(
	(result, { bp, max }) => {
		result[bp] = { min: min || 0, max };
		min = max;
		return result;
	},
	{}
);

var defaults = {
	padding: 0,
	maxWidth: null,
	margin: 0,
	span: 12
};

// Container 

var padding = {
	xxs: 20,
	sm: 40,
	lg: 60
};

var maxWidth = {
	small: {
		sm: 620,
		md: 700,
		lg: 700
	},
	medium: {
		xxs: 560,
		sm: 620,
		md: 850,
		lg: 850
	},
	large: {
		xxs: 1080
	},
	xlarge: {
		xxs: 1480
	}
};

// Grid

var margin = {
	default: {
		xxs: 20,
		sm: 30,
		md: 40
	},
	large: {
		xxs: 40,
		md: 60
	}
};


var columns = 12;
var span = {
	xs: 12,
	sm: 6,
	md: 4,
	xl: 3
};

var layout = {
	padding,
	maxWidth: maxWidth.xlarge,
	margin: margin.large,
	span
};


function flattenLayout (layout) {
	let values = Object.assign({}, defaults);
	return breakpoints.reduce(
		(result, bp) => {
			result[bp] = Object.keys(layout).reduce(
				(subresult, key) => {
					if (bp in layout[key]) {
						values[key] = layout[key][bp];
					}
					subresult[key] = values[key];
					return subresult;
				},
				{}
			);
			return result;
		},
		{}
	);
}

console.log("layout flattened", layout, flattenLayout(layout));


function calculateLayout (layout, context = bpSizes) {
	return Object.keys(layout).reduce(
		(result, bp) => {
			let { min, max } = parent[bp];
			let { margin, maxWidth, padding, span } = layout[bp];
			if (maxWidth && min > (maxWidth + 2 * padding)) {
				min = maxWidth;
			}
			if (!max || maxWidth && max > (maxWidth + 2 * padding)) {
				max = maxWidth;
			}
			result[bp] = {
				min: calculateSpanWidth(min, span, margin),
				max: max ? calculateSpanWidth(max, span, margin) : max
			};
			return result;
		},
		{}
	);
}

function calculateSpanWidth (width, span,...