sodcalculator

10 Tech How-To

CSS Grid Masonry Layout: Lanes & Grid Lines

Guide 10-35322 · Updated · Step by step

This guide explains how CSS Grid’s lane-based alignment (grid lines and tracks) fits into masonry-style layouts, letting you create Pinterest-like columns without heavy JavaScript. You’ll learn the core concepts, then apply them step-by-step to build a responsive masonry grid that uses CSS Grid’s native capabilities.

What You’ll Need

  • A text editor (VS Code, Sublime, etc.)
  • A modern browser that supports CSS Grid (Chrome, Firefox, Safari, Edge)
  • Basic understanding of HTML and CSS
  • Optional: a few images or content blocks to test with

Step-by-Step

  1. Understand the core concept: CSS Grid normally creates rows and columns that align tightly. Masonry layouts break that alignment vertically—items in one column can be taller or shorter than those next to them. The key is to let each column behave like its own stacking context. CSS Grid does not have a native masonry value (except experimental support in some browsers), so we’ll emulate it by defining columns and letting items flow naturally.
  2. Set up your HTML structure: Create a container <div class="masonry"> and place your items inside. Each item should be a direct child, like <div class="item">...</div>. For this example, we’ll use images with varying heights.
  3. Define the grid container: In your CSS, set display: grid; on the container. Then define the columns using grid-template-columns. For a masonry effect, use a fixed number of columns with repeat(), or use auto-fill with a minimum width for responsiveness. Example: grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); This creates as many columns as fit, each at least 250px wide.
  4. Set the row behavior: To allow items to stack vertically without forcing equal heights, use grid-auto-rows: 10px; or a small value like 8px. This sets the height of implicit rows. Then, on each item, set grid-row: span N; where N is the number of rows the item should span. For example, an image that is 300px tall might span 30 rows if each row is 10px. This creates the staggered effect.
  5. Apply the span to each item: You can either manually set grid-row: span 30; on each item, or use a class like .tall and .short to vary heights. For a dynamic approach, you could use JavaScript to calculate the span based on the content height, but for a pure CSS solution, you’ll set fixed spans. Example: .item { grid-row: span 20; } .item.tall { grid-row: span 30; }
  6. Add the gap: Use gap: 10px; (or grid-gap for older browsers) to add space between items. This prevents them from touching and makes the layout readable.
  7. Make it responsive: The auto-fill and minmax() approach already makes columns responsive. For finer control, you can use media queries to change the column count. For example, on mobile you might want 1 or 2 columns, on tablet 3, and on desktop 4. Adjust the grid-template-columns accordingly.
  8. Test and refine: Open your page in the browser and inspect the layout. Adjust the row height and span values until the visual rhythm looks good. Remember that the row height acts as a base unit—smaller values give more control but require larger spans.

Common Mistakes

  • Using grid-auto-rows: auto;—this makes rows size to content, which defeats the masonry effect because rows will align again.
  • Forgetting to set grid-row on items—without spans, items will just fill the grid in normal order, giving a regular grid layout.
  • Setting grid-auto-flow: row; (the default)—this places items row by row, which can cause gaps. For masonry, you want grid-auto-flow: row dense; to backfill gaps, or use column flow (see Tips).
  • Using fixed pixel heights for items—if your images have varying natural heights, the spans might not match, causing misalignment. Use a consistent base unit.

Tips

  • Use grid-auto-flow: column dense; for a different masonry feel: This creates columns that fill vertically first, then move to the next column. It’s often better for masonry because it avoids horizontal gaps. Set grid-template-rows: repeat(auto-fill, minmax(10px, 1fr)); and then let items span columns instead of rows.
  • Combine with object-fit: cover; on images to ensure they fill their grid area nicely without distortion.
  • Use CSS variables for row height and spans to make adjustments easier. For example: :root { --row-height: 10px; } and then grid-auto-rows: var(--row-height);.
  • For dynamic content, consider a small JavaScript helper that calculates the span based on the element’s offsetHeight. This gives a true masonry effect without manual spans.
  • Always test in multiple browsers—CSS Grid is well-supported, but the masonry property is still experimental. Stick to the span technique for maximum compatibility.

Troubleshooting

  • Items are not overlapping or staggering: Check that grid-auto-rows is set to a small value (like 10px) and that items have grid-row: span N. If you’re using grid-auto-flow: row;, try switching to row dense to fill gaps.
  • Gaps appear between items: This usually happens when the total span of items in a row doesn’t add up to the full width. Use dense flow to backfill, or adjust your spans to be more flexible.
  • Items overflow their grid area: If an item’s content is taller than the span, it will overflow. Increase the span value or ensure the content has a max-height. For images, use object-fit: cover; and a fixed height on the item.
  • The layout looks like a regular grid: Make sure you haven’t set grid-template-rows to a fixed value like repeat(3, 200px). That forces equal rows. Use auto rows with a small base.
  • Columns are not responsive: If you’re using auto-fill, ensure the container has a width. If you’re using media queries, check that they are placed after the base styles.

Frequently Asked Questions

Can I use CSS Grid’s native masonry property?

As of now, the masonry value for grid-template-columns or grid-template-rows is only supported in Firefox (behind a flag) and Safari (as of 2023). For production, stick to the span technique described here.

Why do I need to set a small row height?

Setting a small row height (like 10px) gives you fine-grained control over how many rows each item spans. If you set it to 100px, you can only span in multiples of 100, which limits your layout flexibility.

What’s the difference between row dense and column dense?

row dense fills gaps by placing items in the next available row, which can leave vertical gaps. column dense fills gaps by moving to the next column, which is often better for masonry because it keeps columns tight.

Can I use this technique with dynamic content?

Yes, but you’ll need JavaScript to measure the height of each item and set the appropriate span. A simple script can loop through items and set grid-row: span Math.ceil(item.offsetHeight / rowHeight).

Is this better than using flexbox or a JavaScript library?

CSS Grid with spans is lightweight and works well for most masonry layouts. Flexbox can’t do masonry without extra wrappers. JavaScript libraries like Masonry.js offer more features but add overhead. For simple grids, CSS is sufficient.

How do I make the masonry layout work in older browsers?

If you need to support Internet Explorer, you’ll need a fallback like a flexbox-based layout or a JavaScript solution. Modern browsers (Chrome, Firefox, Safari, Edge) all support CSS Grid.

Related

General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.

More in this bed

The whole Tech How-To bed →