Because most sites are built section by section rather than on a shared structure. Each block gets its own padding, its own max width, and its own idea of where the left edge is. Nothing is obviously broken, but the page never quite settles, and readers feel it without being able to name it.
A grid fixes that by making alignment a decision you take once instead of forty times. Every section snaps to the same vertical lines, so headings, images, and buttons line up down the whole page even when they belong to completely different components.
This used to require a framework and a lot of nested divs. It does not anymore. CSS Grid handles it natively, and understanding a handful of concepts properly is enough to build almost any layout you will need.
A grid is a set of invisible columns and rows that content aligns to. Designers have used them in print for a century for exactly one reason: consistent alignment reads as intentional, and inconsistent alignment reads as sloppy, even to people who have no idea what they are looking at.
On the web the grid does a second job as well. It gives you a shared vocabulary. When a designer says a card spans four columns and a developer builds it spanning four columns, the handoff is unambiguous. Without a grid, that conversation happens in pixels and breaks at every screen size.
The grid is also what makes a design system possible rather than aspirational. Components that all agree on the same underlying columns can be rearranged without redesigning them, which is the difference between a real system and a folder of one-off layouts. We went into that in more depth in our guide to building a web design system.
CSS Grid is a real two dimensional layout system, not a set of width classes. Old column frameworks worked by giving elements percentage widths and floating them next to each other. Rows were a fiction maintained by wrapper divs. Grid makes both axes first class.
The setup is a single declaration. MDN puts it plainly: "We create a grid container by declaring display: grid or display: inline-grid on an element. As soon as we do this, all direct children of that element become grid items." No wrapper rows, no clearfix, no framework.
From there you define the tracks. MDN describes a grid track as "the space between any two adjacent lines on the grid", set through grid-template-columns and grid-template-rows. The important shift is that you are describing the container's structure once, rather than annotating every child with a width.
One detail catches people out when they move over. MDN notes that "when we define a grid we define the grid tracks, not the lines. Grid then gives us numbered lines to use when positioning items." You size the columns, and the numbering you place things against appears as a consequence.
Twelve remains the sensible default, and the reason is arithmetic rather than tradition. Twelve divides cleanly into halves, thirds, quarters, and sixths, which covers nearly every layout a marketing site needs without leaving awkward remainders.
That said, you no longer have to force everything into twelve. Grid lets you define whatever track structure a section actually needs, so a hero can be two asymmetric columns and a feature row can be three equal ones without either pretending to be a subdivision of twelve.
Our practice is to keep one page level grid of twelve columns for alignment, then let individual components define their own internal tracks. The page grid keeps everything aligned to the same vertical rhythm. The component grids keep each piece from being distorted by a structure it does not need.
The fr unit distributes leftover space. MDN defines it as representing "a fraction of the available space in the grid container", so a definition of 1fr 1fr 1fr creates "three equal width tracks that grow and shrink according to the available space". No percentages, no accounting for gaps.
That last part is the quiet win. With percentage widths, adding a gutter meant subtracting it from every column and hoping the maths held. With fr, gaps are taken out first and the fractions divide what remains. MDN handles gutters through "the column-gap and row-gap properties, or the shorthand gap", and they simply work.
For repetitive structures MDN points at the repeat notation, so twelve equal columns is repeat(12, 1fr) rather than a line of identical values. Combined with minmax, which MDN describes as a way to "give tracks a minimum size, but also ensure they expand to fit any content", you can express most responsive behaviour in one line.
By describing the rules rather than the screen sizes. A track definition that combines repeat with auto-fit and minmax lets the browser work out how many columns fit and reflow them itself. Cards wrap when they run out of room, at whatever width that happens to be.
This is a genuine change in how responsive design works. The old model was to pick a handful of device widths and redraw the layout at each one. The new model is to state a minimum comfortable width for a card and let the layout follow from it, which handles screen sizes nobody anticipated.
Breakpoints still have a place for the changes that are editorial rather than mechanical, like collapsing a navigation or reordering a hero. We use far fewer of them than we used to, and we cover where they still earn their keep in our notes on responsive breakpoints.
Subgrid lets a nested grid use its parent's tracks instead of creating its own. That solves the most persistent alignment problem in card layouts, where three cards sit side by side and their headings, body text, and buttons all sit at slightly different heights.
MDN describes the problem precisely. Nested grids "are independent of the parent grid and of each other, meaning that they do not take their track sizing from the parent grid. This makes it difficult to line nested grid items up with the main grid." Anyone who has faked this with fixed heights knows the feeling.
The fix is one value. Set subgrid on grid-template-rows and, as MDN puts it, "instead of creating a new track listing, the nested grid uses the tracks defined on the parent". Every card's button now sits on the same line because they share the same rows.
Support is no longer a reason to avoid it. MDN lists subgrid as Baseline widely available, noting it "has been available across browsers since September 2023". That is long enough that we treat it as a normal tool rather than a progressive enhancement.
When a component needs to respond to its own space rather than the screen's. A card in a wide main column and the same card in a narrow sidebar are at identical viewport widths and need different layouts. Media queries cannot tell those apart. Container queries can.
MDN frames it as the direct alternative: container queries "enable you to apply styles to an element based on certain attributes of its container", positioned as "an alternative to media queries, which apply styles to elements based on viewport size or other device characteristics."
The practical benefit for a design system is reuse. As MDN puts it, "Using container queries, the card can be reused in multiple areas of a page without needing to know specifically where it will be placed each time." That is exactly the property a component library needs and rarely has. We went deeper on the mechanics in our guide to CSS container queries.
Performance, barely. Accessibility, potentially quite a lot if you are careless. Grid is native browser layout, so it replaces JavaScript positioning and wrapper markup rather than adding weight. The 2025 Web Almanac puts median CSS at just 77 KB on mobile home pages, against 632 KB of JavaScript, which tells you where the real cost sits.
The accessibility risk comes from grid's ability to place items anywhere regardless of source order. Keyboard focus follows the DOM, not the visual layout. If you visually reorder three items so the last one appears first, a keyboard user still reaches them in the original order, and the page stops making sense to them.
Our rule is that visual order and source order should match unless there is a strong reason otherwise, and that any exception gets tested with a keyboard before it ships. Grid gives you enough rope here to build something that looks perfect and is genuinely difficult to use.
Open your site and check whether the left edges line up. Pick three sections at random, look at where the first character of each heading sits, and see if they share a vertical line. On most sites they do not, and that single inconsistency accounts for a surprising amount of why a page feels unpolished.
Then define one page level grid and move everything onto it before you touch anything else. Twelve columns, one gap value, one max width. Most of the alignment problems on a site disappear at that step, before you get anywhere near subgrid or container queries.
We rebuild a lot of sites that were designed well and assembled inconsistently, and the grid is usually where we start. If your pages feel slightly off and you cannot work out why, we are happy to take a look and point at what is actually causing it. You can find us at phoenix.studio.
Tell us where you want to go. We'll tell you how we'd get you there.