<div class="grid">
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
</div>
<script> CSS.layoutWorklet.addModule('https://codepen.io/tomquinonero/pen/vYZPbxJ.js');
</script>
body {
font-family: sans-serif;
height: 100vh;
display: grid;
place-items: center;
background: #f5b4a5;
}
.grid {
display: layout(masonry);
--padding: 20;
--columns: 2;
width: 50rem;
}
.element {
--brandingColor: #5f64e2;
width: 20rem;
height: 20rem;
background: var(--brandingColor);
border-radius: 4rem;
}
.element:nth-child(2),
.element:nth-child(6),
.element:nth-child(3) {
height: 30rem;
}
.element:nth-child(4),
.element:nth-child(5) {
height: 10rem;
}
registerLayout(
"masonry",
class {
static get inputProperties() {
return ["--padding", "--columns"];
}
async intrinsicSizes() {
/* TODO implement :) */
}
async layout(children, edges, constraints, styleMap) {
const inlineSize = constraints.fixedInlineSize;
const padding = parseInt(styleMap.get("--padding").toString());
const columnValue = styleMap.get("--columns").toString();
// We also accept 'auto', which will select the BEST number of columns.
let columns = parseInt(columnValue);
if (columnValue == "auto" || !columns) {
columns = Math.ceil(inlineSize / 350); // MAGIC NUMBER \o/.
}
// Layout all children with simply their column size.
const childInlineSize = (inlineSize - (columns + 1) * padding) / columns;
const childFragments = await Promise.all(
children.map((child) => {
return child.layoutNextFragment({ fixedInlineSize: childInlineSize });
})
);
let autoBlockSize = 0;
const columnOffsets = Array(columns).fill(0);
for (let childFragment of childFragments) {
// Select the column with the least amount of stuff in it.
const min = columnOffsets.reduce(
(acc, val, idx) => {
if (!acc || val < acc.val) {
return { idx, val };
}
return acc;
},
{ val: +Infinity, idx: -1 }
);
childFragment.inlineOffset =
padding + (childInlineSize + padding) * min.idx;
childFragment.blockOffset = padding + min.val;
columnOffsets[min.idx] =
childFragment.blockOffset + childFragment.blockSize;
autoBlockSize = Math.max(
autoBlockSize,
columnOffsets[min.idx] + padding
);
}
return { autoBlockSize, childFragments };
}
}
);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.