Flexbox and CSS Grid are both powerful layout technologies built into CSS. They have many overlapping abilities. For most tasks, such as vertical centering, I could reach for either one. In some cases, one or the other is the only way to get the job done.
Is one better than the other, given the current state of web standards?
In the event that either Grid or Flexbox would work, I’m now reaching for Grid. I’ll explain why after discussing some various multiline scenarios.
Soon there will be a uniform way to apply consistent spacing between child items, as defined by the parent:
gap: 5px will not affect the outside margin, only the spacing between interior items.
This was inspired by and will eventually supersede Grid’s
grid-gap property. Unfortunately, the only way achieve the same result on multiline (wrapping) items in Flexbox using any browser other than Firefox is the Negative Margin Hack. This is where all the child items get a margin equal to half of the gap. Then to account for the extra space on the outside, the container gets a margin of the same value multiplied by -1. You can only use
:last-child on the items to account for the extra space when you have a single row (non-wrapping flex container).
For multiline grid containers, just apply a
Winner: Grid, but hopefully
gap for flex layout will soon be added to Chrome and Safari.
If you have tracks in both directions (a multi-column and multi-row layout) then your choice depends on the widths of the child items relative to others.
If you want all the items to line up evenly and stack vertically, use Grid.
If you want the items to retain their natural width and not line up vertically, use Flexbox.
The code for Grid requires a
repeat() function to be defined on the container’s
grid-template-columns property. The
repeat function accepts two values. The first for our purpose is either
auto-fit. And the second is a
minmax function, which accepts a value with a fixed unit, and another fixed or relative value.
All together it might look like this:
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
This will give each item a base width of 200px that will scale up as needed.
For Flexbox, just add
Winner: Depends on the use case, but Flexbox is a lot simpler. 🙃
There may be some cases — such as the boundary between two components — where you only want to modify the parent container’s CSS or the children’s CSS.
If you have control over the parent element, use Grid, which defines the children with
If you have control over the child elements, use Flexbox, where the children define their own
If you must use Flexbox for some other reason, you can still define a CSS variable on the parent that will be inherited by the children.
Winner: Depends on the use case, but Flexbox gets a point for versatility. Personally I like having the ability to control all the items on the parent in one place whenever possible, so Grid gets a point too.
One killer CSS Grid feature that’s only landed in Firefox is
subgrid. This allows a child grid item to define its grid children according to the same track definition as the top level parent.
If you had a set of items that internally are split into a top and bottom section with variable amounts of content, you could define two repeating
auto grid tracks at the top level. Then the middle-level child items take up two each of the repeating rows. Then they pass down the track definition so that the top part receives one
auto track and the bottom part receives the other. Now, across the items, the split will be at the same place, so internally they all line up.
Winner: Grid, but you’ll still have uneven layouts in any browser other than Firefox.
For most other use cases, especially when working with one track in one direction with no spacing between items, I would be comfortable using either. That goes for situations where you need vertical centering and relative sizing.
But I find it easier to reason about how the children should be laid out when I’m defining them in one place on the parent element — so Grid wins out most of the time.
Overall Winner: Grid, but know its limitations!
As I mentioned, Firefox has taken the lead in this area. Please ⭐️ / CC yourself on these issues on Chromium and WebKit to make both Flexbox and Grid more powerful in the future!
gapfor Flexbox (Chromium): https://bugs.chromium.org/p/chromium/issues/detail?id=762679
gapfor Flexbox (WebKit): https://bugs.webkit.org/show_bug.cgi?id=206767