loading...

When to use CSS Grid and when to use Flexbox for Multiline Layout

mpuckett profile image Michael Puckett Updated on ・4 min read

Introduction

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.

Gap

Soon there will be a uniform way to apply consistent spacing between child items, as defined by the parent: gap. So, 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 :first-child and :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 grid-gap.

Winner: Grid, but hopefully gap for flex layout will soon be added to Chrome and Safari.

Consistent Sizing vs Automatic Sizing

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.

Grid will line up evenly

If you want the items to retain their natural width and not line up vertically, use Flexbox.

Flex will size automatically according to the content

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-fill or 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 flex-wrap: wrap.

Winner: Depends on the use case, but Flexbox is a lot simpler. 🙃

Container Control vs Item Control

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 grid-template-* and grid-auto-*.

If you have control over the child elements, use Flexbox, where the children define their own flex-basis.

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.

Nested Layout

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.

Subgrid and without Subgrid example

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.

Conclusion

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!

Discussion

markdown guide
 

Great article. Many are unaware how well Grid and FlexBox can work well together.

My strategy: FlexBox for Navigation and informational Footer, I always use Flex on containers that are being iterated or dynamically updated, the wrap feature is gold to ensure sanity when new line starts.

It's Grid for everything else that I need to ensure that a container doesn't surprise me in the browser. Haha!

 

That's a great example of where flexbox shines! Throw a bunch of stuff at it and let it find the best fit. Flex layout is a constraint system, which is great to be able to dip into, but the layout logic can certainly cause surprises. Grid to me feels like building with brick and mortar, much more predictable. We're very lucky to finally have both at our disposal!

🤘

 

I was looking for the article. Now I got it.