CSS Masonry Layout with grid-template-rows: masonry

CSS Masonry layout — items packed into columns with no fixed row height — has been possible only with JavaScript libraries or multi-column CSS hacks until now. The grid-template-rows: masonry (Firefox behind a flag) and the newer masonry display value (Chrome experimental) finally bring true masonry to CSS. A polyfill path using grid-template-columns with subgrid is available for broader support today.

Problem: CSS Flexbox and Grid require JavaScript-calculated heights or multi-column hacks to achieve a true masonry layout — items that fill columns by height rather than rows.

Solution: Use the CSS grid-template-rows: masonry property (behind a flag in Firefox, shipping in other browsers) to enable native masonry in a grid container. Set grid-template-columns to define column widths and let the browser pack items into the shortest column automatically — no JavaScript required.


The examples below show the native masonry syntax, a @supports progressive enhancement pattern, and a CSS-only fallback using multi-column for browsers that do not yet support it.


/* ── Native masonry (Firefox flag / Chrome experimental) ── */
.masonry-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    grid-template-rows: masonry;  /* the magic property */
    gap: 1.25rem;
}

/* ── Progressive enhancement with @supports ── */
@supports (grid-template-rows: masonry) {
    .masonry-grid {
        grid-template-rows: masonry;
        align-tracks: stretch;   /* align items within their masonry track */
    }
}

/* ── CSS-only fallback: multi-column layout ── */
@supports not (grid-template-rows: masonry) {
    .masonry-grid {
        display: block;
        column-count: 3;
        column-gap: 1.25rem;
    }

    .masonry-grid > * {
        break-inside: avoid;
        margin-block-end: 1.25rem;
    }
}

/* ── Card item styles (work in both layouts) ── */
.masonry-grid > .card {
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 2px 8px rgb(0 0 0 / .1);
}

.masonry-grid > .card img {
    width: 100%;
    height: auto;
    display: block;
}

/* ── Responsive columns ── */
@media (max-width: 600px) {
    .masonry-grid {
        grid-template-columns: 1fr;
        column-count: 1;
    }
}


NOTE: In Chrome you must enable the Experimental Web Platform features flag (chrome://flags/#enable-experimental-web-platform-features) to test grid-template-rows: masonry; for production use today the multi-column fallback or a lightweight JS library like Masonry.js is still needed in most projects.