When to Use CSS Grids

What they are, and what they are not

CSS grids are amazingly useful. They take normal, single-dimensional grids into a whole other dimension (literally)! But there are some limitations designers and front-end developers need to be aware of before spending a ton of time refactoring to them…

If you haven’t heard about CSS Grids yet, what are you doing? Go read about them, now! Support for them just dropped in the evergreen browsers, save Safari, which is due out in April. That means that by the end of the year, we could see as high as 50-70% support. (I just made this number up.)

But as I’ve been working with a designer on what this means, and how we can best use CSS grids, I’ve come across a few limitations and things to be aware of before fully adopting CSS grids as the Swiss Army knife of layout tools…

Before I do that, though, let’s talk about what CSS Grids are.

CSS Grids

CSS Grids simply add the Y-plane to a container element’s layout awareness. Typically, browsers lay out elements from left to right (or right to left if you’re in a right-to-left locale). With a grid, the developer can set a series of columns and/or rows — known as “tracks” — for a container’s elements to fall into upon render.

Elements can span rows and columns, columns can be fluid, have max- and min-widths, and so on.

The most obvious use for CSS grids is for layout. Other layout methods like flex box rely on single-track, left-to-right rendering, using manual breaks, row dividers, or other methods to tell the browser when there’s a new row.

With CSS grids, you define in the CSS where things should go, independent of markup order, and with the ability to change the dimensions of the grid.

For example, a class two-column, header and footer layout in flex box:

See the Pen Flex Layout, Basic by Ryan Poe (@baublet) on CodePen.

In CSS grids, this becomes:

See the Pen CSS Grid Layout, Basic by Ryan Poe (@baublet) on CodePen.

(Note: note here that we can specify that the track itself can grow to fill the viewport? A nice benefit of CSS Grids.)

Grids have the benefit of letting us move things around. Want to swap your header and footer? Simple:

See the Pen CSS Grid Layout, Basic by Ryan Poe (@baublet) on CodePen.

Want to add a column to the top right of your header — say, a promotional banner? Add a new track and drop your div into your markup:

See the Pen CSS Grid Layout, Basic by Ryan Poe (@baublet) on CodePen.

CSS grids make your basic page layouts work really well, and really simply. You can even use it to do things like layout a grid of known-width and known-height tiles:

See the Pen Grid by Example 6: Line-based placement span keyword by rachelandrew (@rachelandrew) on CodePen.

What Grids Are Not

CSS grids are not design grids

Grids, however, comes with some limitations. By far the biggest limitation, and one that separates CSS grids from its namesake, is the fact that it isn’t a design grid. It’s a layout grid.

What do I mean?

A design grid, as opposed to a CSS grid, overlays a web page or other design document, intending to have the elements in the page align visually along the grid’s various axes. These grids are intended to establish a visual rhythm and consistency to a website. Pages laid out in a grid look more coherent and unified.

An Ebay site with a grid overlaid. Notice the horizontal visual consistency.

However, on the web, laying out content to a grid is very difficult. We can’t use pixels, since we need to design for virtually every display size between 280px and 20,080px. Percentages work well for top-level elements. But on subgrids (grids within grids), there is very little hope of having that grid align with the parent grid without a mess of selectors and edge-case nightmares.

In addition, percentages won’t help us for vertical units — if you want your grid column gaps to be the same as your row gaps, percentages won’t work. (This is because the browser calculates the percentage as part of the parent value. If the width and height are different, the row gaps and column gaps will be different. Indeed, most browsers don’t even know how to calculate the row gap as a percentage, so won’t take the unit.)

I tinkered with a ton of different ways to ensure visual consistency using just blocks and guides to no avail. Subgrids will just never want to align perfectly to a parent grid automatically.

Notice how the grid comprising the three “hello” containers only slightly aligns to the overall grid — and this is my best attempt, abandoning the grid column gaps property.

With some difficulty, you can definitely use a CSS grid to help you enforce a visual consistency, but you will have to use a mix of CSS grids and flex box row/col grids to do it — along with a fair bit of discipline and oversight of your markup and development process.

One notable exception is if you discard column gaps and margins entirely, and opt to control spacing within columns. The problem? This just shoves the problem of aligning items down the pipeline, to elements within columns, rather than columns. And the whole purpose of a grid system is to alleviate spacing issues between individual elements so that every single element doesn’t need to specify its own spacing…

Bottom line: it’s probably not worth your time trying to fit an entire website into a CSS grid apart from basic layout. CSS grids are not meant for this use case. It can help, especially with layouts, but it’s not a panacea.

CSS Grids are not a replacement for flex box

Flex box solves a very specific, but common problem on the web: how do we ensure that a series of block-level elements stay next to each other with consistent, expected behaviors?

Flex box lays out items along a single axis (x or y; horizontal or vertical). It’s very, very good at that. And while grid can do that, too, don’t use grid where you can use flex box instead. For example, use a CSS grid with a flex box fallback for your layout, but sometimes, you just want two columns, side-by-side on desktop; yet horizontal on mobile. Sure, you can do this with a CSS grid and a flex box fallback, but why bother writing all that code and worrying about the support for grids?

See the Pen Flex Panel by Ryan Poe (@baublet) on CodePen.

On the other hand, do you have a grid of products that you know will almost always contain multiple rows? Do these rows contain items that are of a specific, known height and width? Perfect.

See the Pen Product Grid with Flex Box Fallback by Ryan Poe (@baublet) on CodePen.

But note how the flex box fallback isn’t so hot? that’s because…

CSS grids are not a replacement for masonry

Masonry is a way of organizing tiles of known or unknown height and width into a dense grid of items. Think Pinterest, but with even more flexibility. It uses javascript because, at least at the moment, it has to. You can fake a masonry-style grid using the techniques I showed above, but if you don’t know the width and height of your items, they won’t fit in your grid quite right.

Remember, grids are created by defining your tracks in terms rows and columns with specified heights — or, at least, fractions/percentages. Masonry doesn’t really care about tracks, it just pieces together an assortment of odd-sized block-level elements as well as it can using absolute positioning and a series of calculations about the container object and its child elements.

CSS grids doesn’t get us any closer to the browser doing this for us, unfortunately.