CSS Grid vs. CSS Flexbox — How and when to use them

Berker Erol
CSS Explained & Illustrated.
8 min readOct 13, 2019

One of the major questions people ask when they learn about CSS Grid are “Does this replace Flexbox?” or “Should I just use Grid instead of Flexbox?”. That’s not really how things will work. CSS Grid has been invented to do things that Flexbox couldn’t do, and Flexbox still remains as a great tool to do things that grid cannot do.

In addition, as developers, we’ll keep using the traditional CSS parts that have been known to us for a long time, such as float or flow. The way a web page gets laid out, the way the content flows down the page in a block direction, or in-line direction constitutes the part of the bigger picture that we need to understand, and eventually implement the Grid within that picture. This article will help you how to understand the logic behind CSS Grid and CSS Flexbox.

Laying out your page with Grid is different from Bootstrap or Foundation frameworks in that you would probably end up using the Grid on certain parts of your page, and not for the whole of the page. Most likely, you will have a container with child items where you would handle the layout of the latter with Grid. Having said this, it is now time to jump on spotting the major difference between Grid and Flexbox.

Major difference 1: one-directional vs. two-directional layout aspect

Firs of all, Flexbox is one-directional, and Grid is two-directional. It is crucial to grasp the logic behind this: Flexbox is interpreted by the browser either in row — that’s the default, or in column. When laying out the items, the browser doesn’t calculate the information across the resulting rows, it tries to lay your items in your specified direction.

The Grid, on the other hand, is two-directional, and it will always want to lay the items based on your specifications for both columns and rows. It will calculate the logic by taking both into account, and render your page accordingly.

Here is a diagram of CSS Grid where items are laid out in both directions:

Diagram of CSS Grid where items are laid out in both directions

Observe how items are laid out with respect to tracklines, the grid template rows or columns that you specify.

Diagram of CSS Grid with tracklines

And here’s another pair of diagram that predict how things might work out with Flexbox where calculations for each row are being done one at a time with no regard to the other rows.

Diagram of CSS Flexbox where items are laid out in row direction

And you can actually see how things don’t line up vertically.

Diagram of CSS Flexbox that shows items are not laid vertically

Here is a diagram where Flexbox is good at and Grid is good at :

Diagram showing CSS Grid and CSS Flexbox Major Difference in layout

One thing Grid can do, and Flexbox cannot handle is when you intentionally want to overlap items. For example :

Image source : https://labs.jensimmons.com/

In the above case the visuals are not background images but actual HTML elements. In the case where you’d like to overlay elements, Grid will give you more control, and make your markup simpler and accurate. As a result, your code will be easier to maintain. Had we used Flexbox, the above would be impossible. What is more is that sometimes you would need to add some other divisions to get the desired layout. Observe the diagram below to understand this peculiar aspect of Flexbox.

Impossible to implement two different layout direction with CSS Flexbox

You cannot establish the above layout with Flexbox because the direction of your layout changes within the container. It is thus impossible to set two directions for its children by the Flex parent — here, the Flex parent is the outer div element with a “container” class.

Notice that the first two items on the left are laid out in column direction inside the container whereas the third item is in row direction. To achieve this with Flexbox, you would need two additional divs in your HTML, one of which would own the two items on the left while the other would own the one on the right. You would also need to specify different directions for those new parent divs.

Major difference 2 : Content-first vs layout-first aspect

Another major difference between Flexbox and Grid is that Flexbox takes basis in the content while Grid takes basis in the layout. Since Flexbox is one directional, the content inside the items themselves determines how they’re laid out if we display them in a Flexbox. However, this will not happen by only writing { display: grid; }, because you first need to tell the number of columns and rows in order for the items to be laid out by the browser. There’s a default, and it is one row by one column, so the browser will actually end up putting every item inside a cell. This explanation will become clearer with the header example we’ll observe below. I created the same basic header by first using Flexbox and then using the Grid.

Before we jump on discovering this aspect, let us be reminded of the following:

  1. The display property specifies if/how an element is displayed.
  2. Every HTML element has a default display value depending on what type of element it is. The default display value for most elements is either block or inline.

Source : https://www.w3schools.com/css/css_display_visibility.asp

When we display the children div items inside the header in Flexbox by writing { display : flexbox; }, they are laid out inside a row, one after the other. Now, the above-mentioned one directional aspect of Flexbox emerges here. By default, this direction is set to row, and you can overwrite it by specifying: { flex-direction : column; }, if need be.

Displaying div items in row direciton with Flexbox.

Check out Flexbox Step 1 here:

If you want to move the logout div to the far right — without editing your HTML, you need to give a margin value to it. However, bear in mind that this practice of assigning margins to your nested elements will result in a messier code that is harder to maintain.

Giving a margin auto to the child div item inside Flexbox container

Check out the Flexbox Step 2 out here:

Now, if you need to achieve a similar layout by using the Grid, simply writing { display : grid; } will not actually make them line up one after another inside a row. Why? Because your Grid wants more information from you! It needs the number of columns (and eventually rows) that you’d like to assign to the parent of those divs — the header.

Check out the Grid Step 1 here

Notice how I am using the repeat operator in CSS to create 10 different columns. The number of rows is not specified, and it is computed to 1 by default. You can actually inspect these Grid lines by using Firefox Developer Edition’s inspect tools. Focus on the dashed lines in the snapshot below, these are the column lines we created with the repeat operator. Notice also how the lines for the row are shown differently — they are closer to being dotted rather than dashed.

Here, I will digress from the content-first vs. layout first aspects to explain a tiny detail concerning those lines. Hold on, it will make the things super clear for you!

The reason why these grid lines are shown differently is because we explicitly specified the number of columns, and the number of rows was implicitly defined by the browser. Had I specified number of rows, those lines would change from being dotted to dashed in the inspect window of Firefox. Why is this important? This knowledge will be useful to you as you are laying out multiple components inside a container and want to span your items through multiple grid lines. (You can learn more about Grid spans here.) To wrap the explicit-implicit grid lines, you can check out this diagram created by Wes Bos below:

Image source: Wes Bos’s course on CSS Grid.

Now that we set our Grid layout by specifying our grid template, it is now time to put that logout div at the end. This is actually super easy with Grid, since you can control from which trackline — the correct term for those dashed explicit lines — your element will be laid out. You can specify it by writing grid-column: 10, and your element will be placed at the start of the 10th trackline. Notice how I am targeting the div element with the nth child operator, but I could have also assigned to an id or class, and targeted it with those.

Check out Grid Step 2 here

As we have seen from the above examples, both CSS Grid and CSS Flexbox come with a predefined logic that we must learn to use in order to achieve the layout we would like to have.

Flexbox inside a Grid — best of both worlds

Go ahead and use Firefox Developer Edition inspect tools to understand the use of Grid and Flexbox on this web page.

Jen Simmon’s example page where Flexbox is nested in a Grid container

At some point, you will want to strategically implement both Flexbox and Grid. Nesting the Flexbox inside a grid is the right way to go since the opposite will result in uncontrolled behavior. In the example above, it would be perfect to use Grid for the page layout, and then Flexbox to align the content inside the header. This’ll give you the best of both worlds, and it will actually make your web page responsive without you having to write media queries for each device.

Conclusion

CSS Grid is a two-dimensional system, meaning it can handle both columns and rows, unlike Flexbox which is a one-dimensional system (either in a column or a row). Another core difference between CSS Grid and Flexbox is that CSS Grid’s approach is layout-first while Flexbox’ approach is content-first. I believe the main goal should be understanding the edge cases of both, and try implementing them together to achieve detailed and responsive web page layouts.

--

--

Berker Erol
CSS Explained & Illustrated.

Full-stack developer in Montreal, formerly architectural designer — McGill alumni.