Stax
Tools
developer-toolscsswebfrontend

CSS Grid in 2026: Subgrid Is Everywhere — Here's How to Actually Use It

CSS Subgrid reached full cross-browser support in 2023 and is changing how developers build complex layouts. This guide covers the Grid fundamentals you need, how Subgrid solves the alignment problem, and when Grid beats Flexbox.

Harshil
Harshil
··5 min read
🌐

This article is currently only available in English. A हिन्दी translation is coming soon.

CSS Grid in 2026: Subgrid Is Everywhere — Here's How to Actually Use It

CSS Grid received its most significant upgrade since launch when Subgrid shipped in all major browsers — Chrome 117 (August 2023) was the last holdout after Firefox (2019) and Safari (2022). As of 2026, Subgrid is supported by over 94% of global browser traffic according to Can I Use. If you learned Grid before 2023, there is a meaningful addition to revisit.

This guide covers the Grid fundamentals that most tutorials skip, the Subgrid pattern that solves the most common layout problem, and a clear answer to "Grid vs Flexbox."


The fundamental mental model: rows AND columns simultaneously

Flexbox is one-dimensional — it arranges items along a single axis (row or column). Grid is two-dimensional — it creates rows and columns simultaneously and lets you place items anywhere in the resulting matrix.

.container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr;  /* 3 columns, middle is twice as wide */
  grid-template-rows: auto 400px auto;  /* 3 rows, middle is fixed height */
  gap: 24px;
}

1fr is a fraction unit — it takes "1 share of the available space." Three columns of 1fr 2fr 1fr distribute space in a 1:2:1 ratio. This is different from percentage widths because fr accounts for gaps automatically.

Build and preview grid layouts in real time at the Stax CSS Grid Generator.


Placing items on the grid

By default, grid items flow automatically into the next available cell. You can override this with explicit placement:

.hero {
  grid-column: 1 / -1;   /* Span from first column line to last */
  grid-row: 1 / 2;
}

.sidebar {
  grid-column: 3 / 4;
  grid-row: 2 / 4;        /* Span two rows */
}

Line numbers start at 1 for the left/top edge and -1 for the right/bottom edge. grid-column: 1 / -1 spans the full width regardless of how many columns exist — useful for responsive layouts where the column count changes.

Named areas make placement self-documenting:

.container {
  grid-template-areas:
    "header header header"
    "sidebar main main"
    "footer footer footer";
}

header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
main    { grid-area: main; }
footer  { grid-area: footer; }

The repeat() and minmax() functions

These two functions handle responsive column definitions without media queries:

/* Auto-fill as many columns as fit, minimum 200px each */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

auto-fill creates as many columns as will fit. minmax(200px, 1fr) means each column is at least 200px but grows to fill available space. On a 900px container with 24px gaps: 4 columns of ~204px each. Resize to 600px: 3 columns. Resize to 250px: 1 column. Zero media queries.

auto-fit (vs auto-fill) collapses empty tracks — useful when you have fewer items than columns would allow and want them to expand rather than leave empty columns.


The problem Subgrid solves

Before Subgrid, every grid item was its own independent grid. If you had a card grid and wanted the card titles and buttons to align across cards of different content lengths — the classic "align baselines across independent items" problem — you had JavaScript workarounds or fixed heights.

The problem:

<div class="card-grid">
  <article class="card">
    <h2>Short title</h2>
    <p>One line of text.</p>
    <button>Read more</button>
  </article>
  <article class="card">
    <h2>A much longer title that wraps to two lines</h2>
    <p>Three lines of content that push the button down further than the neighbouring card.</p>
    <button>Read more</button>
  </article>
</div>

Without Subgrid, the two buttons sit at different heights. With Subgrid:

.card-grid {
  display: grid;
  grid-template-rows: auto auto auto; /* title, content, button rows */
  gap: 16px;
}

.card {
  display: grid;
  grid-row: span 3;          /* Each card spans 3 parent rows */
  grid-template-rows: subgrid; /* Inherit the parent's row tracks */
}

Now all cards share the same row tracks. The tallest title defines the title row height for every card. The tallest content block defines the content row. Every "Read more" button aligns perfectly — no JavaScript, no fixed heights, no hacks.

This is the pattern Subgrid was designed for and it is now production-ready across all major browsers.


Grid vs Flexbox: the actual decision

The "Grid vs Flexbox" framing is largely a false choice — they solve different problems and work well together. But there are genuine preference cases:

Use case Better choice Why
Page-level layout (header, sidebar, main, footer) Grid 2D placement
Card grid with alignment across cards Grid + Subgrid Row/column alignment
Navigation bar (items in a row) Flexbox 1D, spacing between items
Form fields (label + input pairs) Grid Column alignment
Button group Flexbox 1D wrapping
Masonry/Pinterest layout Grid (grid-template-rows: masonry) CSS masonry (Firefox + Chrome flag in 2026)
Centering a single element Either display: grid; place-items: center or Flexbox
Component internals (icon + text) Flexbox Simple 1D alignment
Holy Grail layout Grid Simpler than Flexbox equivalent

The practical rule: use Grid when you're thinking about rows and columns simultaneously. Use Flexbox when you're thinking about a single axis with wrapping.

See Flexbox patterns at the Stax CSS Flexbox Playground.


The gap property: consistent spacing without margin hacks

Before Grid and Flexbox, consistent spacing required margin tricks — margin-right on all items except the last (:last-child { margin-right: 0 }), or negative-margin wrappers. Both are fragile.

gap (formerly grid-gap) adds space between grid cells or flex items without outer margin:

.container {
  gap: 24px;           /* Same gap in all directions */
  gap: 16px 24px;      /* row-gap column-gap */
}

gap is now supported in both Grid and Flexbox, and in multi-column layout. It is the correct way to add consistent spacing in modern CSS.


Practical patterns to copy

Full-bleed layout with content column:

.page {
  display: grid;
  grid-template-columns:
    minmax(16px, 1fr) minmax(auto, 720px) minmax(16px, 1fr);
}
.full-bleed { grid-column: 1 / -1; }
.content    { grid-column: 2; }

12-column responsive grid:

.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 24px;
}
.col-4 { grid-column: span 4; }
.col-8 { grid-column: span 8; }

Auto-responsive card grid:

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 20px;
}

By Harshil Shah, developer and founder at Stax Tools. Browser support figures sourced from Can I Use (caniuse.com) as of May 2026.

Sources & methodology

  1. MDN Web Docs — CSS Grid Layout, developer.mozilla.org
  2. MDN Web Docs — Subgrid, developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Subgrid
  3. Can I Use — CSS Subgrid support table, caniuse.com/css-subgrid (accessed May 2026)
  4. CSS Specification — CSS Grid Layout Module Level 2, w3.org/TR/css-grid-2
Harshil

Harshil

Developer & Founder, stax.tools

Harshil is the developer behind stax.tools, building privacy-first tools that run entirely in your browser.

More by Harshil →

🛠️

Found this useful?

Browse 235+ free privacy-first tools — no login, no uploads, instant results.

Browse tools →
← Back to all posts