DEV Community

Cover image for Back to Basic: Should we use Flexbox or Grid?
Theodorus Clarence
Theodorus Clarence

Posted on • Edited on • Originally published at theodorusclarence.com

Back to Basic: Should we use Flexbox or Grid?

Back to Basic will answer some of my questions when I first started learning CSS. Personally, I think when you start learning CSS, it will be very hard, because CSS has about 520 properties that we can use. Of course, we won't use it all, there are many properties that I still didn't know, but there are plenty of properties that we need to understand to be proficient in CSS. This blog will not cover CSS from the really basic ones, but I will try to show you the implementation.

If you never have used flexbox or grid before, you can check this flexbox guide and grid guide from css-tricks.


Question

When should we use flex or grid?

When I first started learning CSS and know about flexbox and grid, I got confused about when to use flexbox and grid. In this blog, I will try to explain my approach on how to choose between flexbox and grid according to the condition.


Use Case of Using Flex

I always use flex to give a layout that only has 1 dimension (horizontal only or vertical). In this blog, I will give you some example of flexbox use case with some of my project that I have made.

1. Container that has all elements in the center both horizontally and vertically

We usually see this in a landing page

Example:

To achieve this layout, we only need 3 lines of CSS, I suggest you to memorize this combination, because you will use this in many cases.

.container {
  /*  make sure the parent element has height */
  min-height: 100vh;
  /* css to align vertically and horizontally */
  display: flex;
  align-items: center;
  justify-content: center;
}

/* If you want to make a full-page,
make sure the container has a height of the viewport */
Enter fullscreen mode Exit fullscreen mode

2. Divide page into parts

This layout also commonly seen, usually to divide the container into 2 parts with the same width, we can also make it divide into 3, 4, or as many as you want.

Codepen

This layout can be easily achieved by using flex, let's see the HTML first

<div class="container">
  <div class="content">
    <h1>Hello Bambang</h1>
    <p>welcome to my page</p>
    <button>click me</button>
  </div>
  <img class="content" src="https://unsplash.it/700/600" alt="unsplash" />
</div>
Enter fullscreen mode Exit fullscreen mode

As we can see, that div.container has 2 items which is div.content and img.content, so we can make layout that is equal parts.

.container {
  min-height: 100vh;
  display: flex;
}

.content {
  /* this will make it divides in equal parts */
  width: 100%;

  /* you should use flex-basis for this, but flex-basis didn't really works on images, so I use width */
  /* flex-basis: 100%; */
  /* other tag like div works well tho! */
}

div.content {
  /* the first flexbox use case */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

img.content {
  object-fit: cover;
}
Enter fullscreen mode Exit fullscreen mode

by using width: 100% we make the child element to take as much space as possible. Because both of them wants to be 100%, so they compromise and span over 50%.

Keep note that you should replace width: 100% with flex-basis: 100% for IE compatibility purposes (credits to Ihor Vorotnov), but I specifically use width on this one because flex-basis did not really work with images. On other tag like div or headings it works okay.

We could also hard code the width or flex-basis to 50%, but adding this defeat the purpose of dividing content to equal parts because we need to change the percentage each time we add a new child.

If we want to make a responsive design with this layout, we can utilize flex-direction

.container {
  min-height: 100vh;
  display: flex;
  /* add this to make the flex stacked vertically */
  flex-direction: column;
}

@media (min-width: 700px) {
  .container {
    flex-direction: row;
  }
}
Enter fullscreen mode Exit fullscreen mode

So, when we are in a mobile view, flex will stacked vertically (like how HTML normally works), and when we get into larger viewport, flex will make the child elements stack horizontally (check the codepen for demo)

3. Creating Navbar (using space-between)

Codepen

Creating a simple navbar will be very often to do and usually, the layout is spaced apart where the left side is the logo and the right side is the navigation.


<nav>
  <h3>Home</h3>
  <ul>
    <li>Route</li>
    <li>Route</li>
  </ul>
</nav>
Enter fullscreen mode Exit fullscreen mode

nav has 2 children which are h3 and ul. Next, we just need to reset the base style and split the children element with space-between

nav {
  background-color: lightblue;
  display: flex;
  align-items: center;

  /* this property will make the child spaced apart */
  justify-content: space-between;
}

ul {
  /* remove bullet style */
  list-style: none;
  display: flex;
}

ul > li + li {
  /* add space between navigation links */
  margin-left: 2em;
}
Enter fullscreen mode Exit fullscreen mode

All of the examples above actually can be made with a grid too. But, by using grid we need to write more CSS than using flexbox


Use Case of Using Grid

Codepen

Grid is usually used to make a more complex layout. My way of deciding is: if using flex is too hard, then use grid.

Layouting with flex actually can also be implemented for the complex layout, but using grid will be much easier.

1. Making 2 dimensional layout

I usually use grid to create this layout because there is a gap feature to space them out. Spacing things out using flex is going to be harder if we want to make the design responsive

Layout like this will be very easy if using grid, we only need to make it into 2 columns.

<div class="container">
  <div class="item">item1</div>
  <div class="item">item2</div>
  <div class="item">item3</div>
</div>
Enter fullscreen mode Exit fullscreen mode

We will simplify the layout by using div.container and 3 div.item

.container {
  /* container base layout */
  max-width: 700px;
  margin: 0 auto;

  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1em;
}

.item {
  border: 0.2px solid white;
  height: 15em;
}
Enter fullscreen mode Exit fullscreen mode

By using grid-template-columns: repeat(2, 1fr) we set the grid to divide the columns into two, and the item will follow the rule that we set. Last, we add the gap: 1em to create some whitespace.

Grid will be very helpful in responsive design, we only need to change the rules on grid-tem to be 1 column when it is on smaller screen size, and make it to 2 columns in the larger screens

.container {
  /* container base layout */
  max-width: 700px;
  margin: 0 auto;

  display: grid;
  /* no need to add grid template, because grid defaults to 1 column */
  gap: 1em;
}

@media (min-width: 700px) {
  .container {
    grid-template-columns: repeat(2, 1fr);
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Make layout with different sizes

Codepen

I recommend you to use Firefox Dev Tools to see lines indicating the grid numbers.

We approach this kind of layout by making 4 columns and 2 rows, then we assign the row and col placement on each of the elements. For example, the first picture spans over 2 columns and 2 rows. Check this if you have not understand the grid numbering system.

<div class="container">
  <div class="item item1">item1</div>
  <div class="item item2">item2</div>
  <div class="item item3">item3</div>
  <div class="item item4">item4</div>
</div>
Enter fullscreen mode Exit fullscreen mode

We will simplify the layout by using .container as the parent.

.container {
  max-width: 700px;
  margin: 0 auto;

  display: grid;
  /* makes the grid into 4 columns and 2 rows */
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, 1fr);
}

.item {
  border: 1px solid white;
  min-height: 10rem;
}

.item1 {
  grid-column: 1 / 3;
  grid-row: 1 / 3;
}

.item2 {
  grid-column: 3 / 5;
}

/* you can also give value to item 3 and 4,
but because it follows the natural flow of the grid I won't continue */
Enter fullscreen mode Exit fullscreen mode

For responsive design, we can put the image according to the rows and columns that we want, we can also change the template


Summary

Use Grid if using flex is getting too complicated


Originally posted on my personal site, find more blog posts and code snippets library I put up for easy access on my site šŸš€

Top comments (32)

Collapse
 
arvindpdmn profile image
Arvind Padmanabhan

The one-line summary says it all! Nice examples to highlight the differences. I would like to quote from devopedia.org/css-grid-layout :
"CSS Grid doesn't replace Flexbox. Grid items can be flex parents and vice versa."

Collapse
 
theodorusclarence profile image
Theodorus Clarence

Thanks for your addition!

Collapse
 
ivan_jrmc profile image
Ivan Jeremic

It does

Collapse
 
ihorvorotnov profile image
Ihor Vorotnov • Edited

Your example #2 (divide page into parts) won't work in Safari. There's no need to hack around with 100% width, there ape specific flexbox properties for that - flex-grow and/or flex-basis:

.content {
  width: 50%;
  flex-grow: 1;
}
Enter fullscreen mode Exit fullscreen mode
.content {
  width: 50%;
  flex-basis: 50%;
}
Enter fullscreen mode Exit fullscreen mode

Also, this is actually the case when grid would be better / simpler / easier:

.container {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 50% 50%;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
theodorusclarence profile image
Theodorus Clarence • Edited

Thanks for your addition! I edited the post!
It turns out that using flex-basis won't work with images. But it is fine on other tags

Collapse
 
lyrod profile image
Lyrod

Why not "grid-template-columns: 1fr 1fr"? This will produce the same right?

Collapse
 
theodorusclarence profile image
Theodorus Clarence

Correct, I usually use fraction unit too.

Collapse
 
danielo515 profile image
Daniel RodrĆ­guez Rivero

Will be nice if you explain what:

  grid-column: 1 / 3;
  grid-row: 1 / 3;
Enter fullscreen mode Exit fullscreen mode

means.
One third? Nope. One column and three rows? nope. One ror and three columns? nope.
It is not intuitive to mw

Collapse
 
larsejaas profile image
Lars Ejaas

I think a lot of people struggle with grid untill you realize that you are not positioning items in terms of colum- and row-areas, but instead lines.
Lets say we draw 3 colums. That gives us 4 vertical lines. So if the container needs to fill out the 3 AREAS you need to write:
grid-column: 1/4; This means that you start at line 1 and end at line 4.

Collapse
 
danielo515 profile image
Daniel RodrĆ­guez Rivero

Oh my god! Thank you.
That totally make it click for me.
Thanks

Thread Thread
 
larsejaas profile image
Lars Ejaas

Your' welcome šŸ˜ŠšŸ‘

Collapse
 
theodorusclarence profile image
Theodorus Clarence

Check this if you have not understand the grid numbering system.

You can look it up at the link that I referred, after that with the numbering illustration I put up, it should be intuitive enough! Good luck šŸš€

Collapse
 
keefdrive profile image
Keerthi

Nice article ...in short Use flex for one dimensionl group of things ie things that need to be placed in a row only, or things that need to be placed column only. ie nav bar = things in a row. With flex you cannot control both row and column.

Use CSS grid for 2 dimensional placement where you want to cotrol the row and column placements. ie the complex layouts of a website.

In flex box you can acheive many things that CSS grid can do, but you have to start nesting containers, which ends up over complicating.

Collapse
 
theodorusclarence profile image
Theodorus Clarence

Great recap!

Collapse
 
kalashin1 profile image
Kinanee Samson

Grid and Flex box actually goes well together, but grid is simpler and removes a lot of unnecessary code

Collapse
 
csorbamatyi profile image
Matyi Csorba

Thank you!
*insert Thank you! meme
;)

Collapse
 
thomasledoux1 profile image
Thomas Ledoux • Edited

Great article!
Note that the gap property can also be used to add spacing between your elements in a flexbox layout: caniuse.com/flexbox-gap.
It is supported by all major browsers by now :-)

Collapse
 
theodorusclarence profile image
Theodorus Clarence

Thanks for your addition. Yep, finally ios & safari is supported, we can start using it now, no more .flex > * + * šŸ˜¬

Collapse
 
theccode profile image
Eric A. Kumah

With those tiny bits of rows and columns? Wow, Grid says divide and conquer! Adjust in order to fit into any tiny bit of space available; Flexboxes even admit they would employ the services of a grid if necessary! Flexbox has the ability to line things up in one dimension (horizontal) but hey, grids with their rows and columns do the same in 2-dimensions! Rows x Columns.. capable of adjusting based on what's going into the grid.

Collapse
 
ivan_jrmc profile image
Ivan Jeremic

I do everything with grid, it is less code and who cares about IE.

Collapse
 
theodorusclarence profile image
Theodorus Clarence

Nice! I think with grid-auto-flow it can easily replace flexbox now, it is also easier to understand grid than flexbox.

Collapse
 
ivan_jrmc profile image
Ivan Jeremic

Yes grid makes just more sense and you can picture it in your head

Collapse
 
elischei profile image
Eli H. Schei

Great overview!

Collapse
 
natalia_asteria profile image
Natalia Asteria

I love how the text in the "Divide page into parts" codepen is "Hello Bambang".