🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
CSS MASTER CLASS /// VISUAL ENGINEERING /// LAYOUT DESIGN /// ANIMATION LAB /// CSS MASTER CLASS /// VISUAL ENGINEERING ///

Masonry Layout: Packing Content Without Wasted Space

Understand exactly why standard CSS Grid rows leave gaps around shorter items, how true masonry layout packs content into the shortest column instead, and which implementation approach is realistic to ship today given current browser support.

Total XP: 0|💻 css XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

Masonry Layout

Gapless, Pinterest-style packing.


🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

Masonry is one of the most recognizable layout patterns on the web, and one CSS Grid's strict row model was never quite able to produce natively — until a proposed extension started closing that gap.

1Why Standard Grid Rows Structurally Can't Produce Masonry

CSS Grid's row model is intentionally strict and predictable: every item placed in a given row shares that row's height, and that height is determined by the row's tallest item. This is exactly the right behavior for tabular, form, or dashboard layouts where alignment across a row matters — but for a photo gallery or card feed with wildly varying natural heights, it produces visually awkward gaps beneath shorter items.

This isn't a bug or a limitation to work around with clever grid-template-rows values — it's a fundamental property of how Grid's row-based algorithm works. True masonry requires an entirely different placement algorithm, one that tracks column heights independently rather than committing every item to a shared row.

.grid { display: grid; grid-template-columns: repeat(3, 1fr); }
/* Item 2 is shorter than item 1 and 3 in its row — gap left below it */
localhost:3000
⚠ Row-Locked GapsStandard grid rows leave predictable but visually wasteful gaps beneath shorter items — an inherent property of the row model, not a bug.

2The Masonry Placement Algorithm

Masonry layout tracks the current accumulated height of each column independently, and places every new item into whichever column is currently the shortest, then updates that column's tracked height. This is precisely the algorithm behind Pinterest's board layout, and it's what the proposed native grid-template-rows: masonry value implements directly at the CSS engine level, keeping items in their original document order while still achieving tight, gapless packing.

A subtlety worth understanding: true masonry (as implemented natively or by dedicated JS libraries) preserves DOM order — item 4 always comes after item 3 in the document, even if it visually lands in a different column. This differs from some naive 'shortest column' implementations that reorder the DOM itself, which can break both keyboard tab order and the natural reading order for screen readers.

.masonry {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: masonry;
}
localhost:3000
✓ Gapless, Order-PreservingEach item packs into the currently shortest column while staying in its original document order — no visual gaps, no accessibility order disruption.

3What's Actually Realistic To Ship Today

Native masonry (grid-template-rows: masonry) is a genuinely elegant solution, but as a newer proposal its cross-browser support isn't yet universal — check current compatibility data before relying on it without a fallback for your specific audience. Two practical alternatives exist today: CSS multi-column layout (columns: 3), which is very broadly supported and produces a visually similar packed effect, though it fills columns top-to-bottom in source order rather than shortest-column-first, which can look subtly different for very uneven content; or a small, well-tested JavaScript masonry library for projects that need pixel-perfect, shortest-column packing with guaranteed support everywhere.

The practical decision usually comes down to how tightly-packed the visual result needs to be, and how broad the target browser support requirement is — multi-column is often 'good enough' for many real designs, while JS libraries remain the safe universal choice for cases where a Pinterest-exact result is a hard requirement.

.masonry-fallback {
  columns: 3;
  column-gap: 16px;
}
/* Broadly supported today, visually close approximation */
localhost:3000
Native masonry: elegant, maturing support
Multi-column: broad support, close approximation
JS library: universal, pixel-perfect

4Step-by-Step Breakdown

The Pinterest Layout, Without A Grid Gap. A regular grid lays items out in strict rows — every item in row two starts below the tallest item in row one, leaving gaps under shorter neighbors. Masonry layout instead packs each new item into whichever column currently has the least content, like bricks settling into the shortest gap, eliminating that wasted space entirely.

Why Regular Grid Rows Leave Gaps. In a standard grid, every row's height is determined by its tallest item, and every item in that row shares that same row boundary — a short item simply leaves empty space below it before the next row begins. This is correct, predictable grid behavior, but it's visually wasteful for content like photos or cards with wildly varying natural heights.

Why Regular Grids Gap. In a standard CSS Grid, why does a shorter item in a row leave visible empty space beneath it?

  • It's a layout bug that should be fixed with padding
  • Every item in a row shares that row's height, which is set by the row's tallest item
  • It doesn't actually happen in a normal grid

Masonry Packs Into The Shortest Column. True masonry layout tracks the current height of each column independently and places each new item into whichever column is currently shortest, rather than locking items to strict shared rows — the defining visual signature of a Pinterest-style board with no wasted vertical space.

Masonry Placement Logic. How does masonry layout decide which column a new item goes into?

  • It always cycles to the next column in order, ignoring height
  • It places the item into whichever column currently has the least accumulated content height
  • Column placement is effectively random

Today's Practical Implementation Options. Native grid-template-rows: masonry is a genuinely promising proposal, but as of this lesson its cross-browser support isn't universal, so production masonry layouts today typically still use either multi-column layout (column-count, which produces a similar but not identical visual effect) or a small amount of JavaScript for true item-order-preserving masonry.

Practical Masonry Today. Why might a production project use column-count (multi-column layout) instead of native masonry today?

  • Because it produces a visually identical result with no trade-offs
  • Because native CSS masonry doesn't yet have universal cross-browser support, and multi-column is widely supported
  • Because native masonry syntax doesn't actually exist

Masonry Layout Understood. You now understand exactly why regular grid rows leave gaps that masonry avoids, how the native masonry proposal packs items into the shortest column, and which practical implementation approaches are reliable to ship in production today given current browser support.

Build A Masonry-Style Layout. column-count splits content into multiple flowing columns, a stable way to approximate masonry layouts.

Level Up 🚀

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1True Masonry Implementations Must Preserve Document Order For Keyboard And Screen-Reader Users

An implementation that visually reorders items into columns (via absolute positioning based on JS-measured heights, for instance) without preserving the underlying DOM order can produce a confusing, illogical tab and reading sequence — verify the DOM order still matches the intended reading order regardless of visual placement.

2Multi-Column Layout's Reading Order Differs From True Masonry And Should Be Verified For Content Comprehension

CSS multi-column fills columns top-to-bottom before moving to the next column, meaning the visual reading order for sighted users can differ from a screen reader's linear DOM-order reading — worth confirming this doesn't create confusing content sequencing for a given design.

SEO Implications

  • 1

    JavaScript-Based Masonry Libraries Can Introduce Layout Shift If Not Carefully Implemented

    A masonry library that measures and repositions items after images load can cause a visible reflow, directly harming Cumulative Layout Shift, a Core Web Vitals metric search engines weigh.

  • 2

    Native CSS Masonry (Where Supported) Avoids JavaScript-Driven Reflow Entirely

    Because native masonry is computed by the browser's layout engine during the initial layout pass rather than measured and repositioned after the fact by script, it avoids the JS-masonry reflow problem outright.

Best Practices

Reserve Image Aspect Ratios Explicitly When Using Any Masonry Approach With Images

Declaring aspect-ratio or width/height on images prevents layout shift as they load, regardless of whether the masonry itself is native, multi-column, or JS-driven.

Verify Reading/Tab Order Independently From Visual Packing Order For Any Masonry Implementation

Whichever approach is used, confirm that keyboard tab order and screen reader reading order still make logical sense, since masonry's visual packing can differ from strict top-to-bottom, left-to-right document flow.

Frequent Bugs

THE BUG

A masonry gallery visibly reflows and jumps around shortly after the page loads.

THE FIX

A JavaScript masonry library is measuring image heights after they load and repositioning items; reserve image space with aspect-ratio ahead of time to prevent the shift.

THE BUG

Keyboard tab order jumps confusingly between visually distant items in a masonry layout.

THE FIX

The masonry implementation is repositioning elements without preserving DOM order; use an approach (native masonry or a library) that keeps the underlying document order intact regardless of visual column placement.

Real-World Examples

A Photo Gallery Using Multi-Column As A Broadly-Supported Masonry Approximation

A blog's image gallery using CSS multi-column layout to achieve a packed, Pinterest-like visual effect without requiring JavaScript or newer, less broadly-supported CSS features.

.gallery {
  columns: 3;
  column-gap: 12px;
}
.gallery img {
  width: 100%;
  margin-bottom: 12px;
  break-inside: avoid;
}

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Expecting standard CSS Grid rows to automatically produce masonry-style packing

/* Doesn't produce masonry */ .grid { display: grid; grid-template-columns: repeat(3, 1fr); } /* Does */ .grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: masonry; }

The Solution //

Use grid-template-rows: masonry (where supported), multi-column layout, or a JS library — standard grid rows fundamentally can't produce shortest-column packing.

The Error //

Not reserving image dimensions, causing layout shift as a masonry gallery loads

img { aspect-ratio: 4 / 3; width: 100%; object-fit: cover; }

The Solution //

Set aspect-ratio or width/height on images so their space is reserved before they finish loading.

Lesson Glossary

[01]Masonry Layout

A layout packing items into the shortest column, avoiding row-based gaps.

Code Preview
Pinterest-style

[02]grid-template-rows: masonry

The proposed native CSS value for masonry layout.

Code Preview
masonry

[03]Multi-Column Layout

A widely-supported CSS feature approximating masonry visually.

Code Preview
columns: 3

[04]Document Order Preservation

Keeping items in their original DOM sequence despite visual repositioning.

Code Preview
Accessibility requirement

Continue Learning