Should I use Grid or Flexbox?

In my recent presentation at Fluent Conf I demonstrated the common features and also the differences between Flexbox and CSS Grid Layout. Right now, we can only use CSS Grid Layout by enabling browser flags, however once Grid ships there will be many layout tasks where we could argue for the use of Grid or Flexbox as the solution. Here are some thoughts.

Major layouts vs. UI elements

When people first encounter CSS Grid Layout, they tend to think of Grid as being the controller of the major page layout, providing a framework for headers and sidebars, main content and footers.

You can see this use case in this example. Only the direct children become a Grid Item and so by declaring a Grid on my wrapper the header, panel, content and footer all become Grid Items and can be placed onto that Grid. Any elements inside those main containers can then be laid out by whichever method makes sense.

Flexbox is not so well suited to creating these types of layouts. It is certainly possible to create a simple layout like the one above using Flexbox. However once flex items wrap, each row (or column if working with flex-direction: column), becomes a flex container itself. Space distribution happens across that row or column, you lose the ability to line things up with items in rows above.

Here we find the biggest difference between Grid and Flexbox. Flexbox is essentially for laying out items in a single dimension – in a row OR a column. Grid is for layout of items in two dimensions – rows AND columns.

One dimensional vs. Two dimensional

Here is the most simple example of one versus two dimensional layout.

See the Pen Flex and Grid demo by rachelandrew (@rachelandrew) on CodePen.

In the top layout I am using Flexbox to display a set of “cards”. The container has flex-wrap set to wrap and so the flex items wrap onto two lines, I have set flex-grow to 1, flex-shrink to 1 and flex-basis to 200 pixels. So my ideal box width is 200 pixels, but items are able to grow larger and shrink smaller.

If my viewport is at a small enough width to display three boxes on row one, two boxes then wrap below. As flex-grow is set to 1, this means that the space leftover after the flex-basis value has been removed is shared equally between those boxes. Row one has three boxes, which are narrower than the boxes on row two where there are only two boxes.

This is how flexbox works. However, most of the flexbox problems I am asked about are due to developers trying to make flexbox do layout in two dimensions. This is where you need Grid Layout.

In the Grid version we define our grid on the wrapper element, the Grid Items then just drop into the Grid Cells already defined. So an item can line up with other items in the row but also in the column. If we want one of our items to stretch over two column or rows tracks we would need to target that item in some way.

Working from the content out vs. working from the Grid definition in

What we see in the above example is how when we use Grid Layout we declare our grid and the content of any grid item then has to adapt to fit the shape of the area it is placed in.

If you have a bunch of items, don’t need them to line up with any other elements, but just want them displayed evenly and flexibly, you want flexbox. The most basic of examples demonstrates the behaviour of items getting an equal amount of space between them using justify-content: space-between.

See the Pen Flexbox: distributed alignment by rachelandrew (@rachelandrew) on CodePen.

Grid implements the space distribution and alignment properties that are part of the Box Alignment Module, so there are possibilities to play with the alignment and spacing of grid items to some degree, but the fact remains that due to the two dimensional approach of grid, you can’t make one row of the grid behave differently to the one above. Instead you’ll need to change the properties on the individual grid items. Making them span more cells, or use different alignment values.

So there is your choice. Do you want to let your content control the way it is displayed, on a row by row or column by column basis? That’s flexbox.

Or, do you want to define a grid, and either allow items to be auto-placed into the cells defined by that grid, or control their positioning using line-based positioning or grid template areas. That’s grid.

If you want to see a lot more grid examples, take a look at my collection on Grid by Example.

12 Comments

Andrew March 30, 2016 Reply

Thanks for the article.

Are there any polyfills (gulp or something) for using grid yet? Looks like it’s still heavily unsupported.

Sten Hougaard March 30, 2016 Reply

Very interesting. I am actually building a two dimensional grid system at the moment which is based on idea of “element media queries”. You can nest grid containers too. I hope to show it as a prototype on Codepen soon 🙂
I am also thinking about coding a PostCSS plugin for easy generating custom two dimensional grids.

/Sten

Darshak Parikh April 1, 2016 Reply

A very informative article.

> Flexbox is essentially for laying out items in a single dimension – in a row OR a column. Grid is for layout of items in two dimensions – rows AND columns.

That sums it up really well.

Bryan April 11, 2016 Reply

Why not include the -webkit flag in your examples so it works in webkit/safari tech preview?

Bitcollage April 13, 2016 Reply

@Andrew a polyfill for grid-layout is very complex. I thought about it, to develop according https://drafts.csswg.org/css-grid/ but i have no time ( many other projects )

Peter April 14, 2016 Reply

The fact that Grid is supported by literally no browsers by default now seems like something that shouldn’t be breezily brushed away in a parenthetical at the start of the article.

Francisco April 14, 2016 Reply

Hi, I just made a library based on Flexbox since it’s more compatible than Grid ( http://francisco.io/flexpoint/ ). I love how many different things you can do with it, but it took a while to get used to the syntax and cases. I hope the grid specification is easier to understand (:

Rachel Andrew April 14, 2016 Reply

In general once Grid is available I’m not sure polyfilling it would be a great idea. I’d be more keen to initially use it as an enhancement (perhaps within @supports rules).

@Bryan given that Grid isn’t actually available live anywhere yet I chose not to so as not to clutter the code examples.

@Peter I’m not sure what about the opening statement is “breezily brushing away” this fact. I’ve been writing about Grid for 3 years or so, I don’t open every blog post with a long statement about support.

Mike Graham April 17, 2016 Reply

Fantastic video.

David Plunkett April 17, 2016 Reply

Creating responsive percentage based grids with Flexbox was surprisingly simple and worked great for all browsers except Firefox. Sadly the vertical percentage margins are calculated differently and defaults to 0px (i.e. they collapse). I believe this is actually the correct behaviour, though can’t help but feel this is a missed opportunity whilst we wait for CSS Grids to become better supported.

Zen Web December 30, 2016 Reply

So where are we now in terms of actual commercial implementations of Flexbox/Grids based websites? Do current browsers support them and what backward compatibility strategies are there for browsers that don’t support it?

Tim January 29, 2017 Reply

Just FYI, the serif text in this article looks fuzzy, like you have an odd anti-aliasing algorithm on it or something.

Leave a Reply