--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="icon" href="data:,">
+ <title>minimal-masonry</title>
+ <style>
+ :root {
+ counter-reset: div-counter;
+ --text-color: hsl(216deg 80% 10%);
+ }
+
+ body {
+ font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
+ background: hsl(216deg 20% 90%);
+ color: var(--text-color);
+ }
+
+ header {
+ display: flex;
+ justify-content: center;
+ }
+
+ main {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
+ gap: 8px;
+ inline-size: min(100% - 16px, 1440px);
+ margin-inline: auto;
+ }
+
+ div {
+ display: grid;
+ place-items: center;
+ border: 2px solid var(--text-color);
+ border-radius: 4px;
+ filter: brightness(90%);
+ transition: filter 500ms;
+ }
+
+ div:hover, div:focus {
+ filter: brightness(100%);
+ transition: filter 150ms;
+ }
+
+ div h1::before {
+ counter-increment: div-counter;
+ content: counter(div-counter);
+ font-weight: 900;
+ font-size: 3rem;
+ }
+ </style>
+</head>
+
+<body>
+ <header>
+ <h1>minimal-masonry</h1>
+ </header>
+
+ <main></main>
+
+ <script>
+ const main = document.querySelector('main');
+ main.insertAdjacentHTML('beforeend', '<div><h1></h1></div>'.repeat(20));
+
+ let rng = new Uint16Array(40); // 2 values used per object = 20 total objects
+ window.crypto.getRandomValues(rng);
+ rng = [...rng]; // Need to spread to a non-typed array to use .pop()
+
+ // All length units are px
+ const gridRowHeight = 8;
+ const minimumDivHeight = window.innerHeight / 12;
+ const maximumDivHeight = window.innerHeight / 4;
+ for (const div of main.children) {
+ // Random height between 1/12 the viewport and 1/4 the viewport
+ const height = rng.pop() % (maximumDivHeight - minimumDivHeight) + minimumDivHeight;
+ const color = `hsl(${rng.pop() % 360}deg 40% 60%)`;
+
+ div.style.setProperty('height', `${height}px`);
+ div.style.setProperty('background', color);
+
+ // This is where the masonry layout is implemented. Since grid-template-rows is not set on <main>,
+ // both row height and row count are implied by the children.
+ div.style.setProperty('grid-row-end', `span ${Math.ceil(height / gridRowHeight)}`);
+ }
+ </script>
+</body>
+
+</html>
\ No newline at end of file