codete CSS Flexbox or Grid Which to Choose and Why main c956e27a5c
Codete Blog

CSS Flexbox or Grid: Which to Choose and Why?

Lukasz Milik cropped f52ae05866

04/02/2021 |

9 min read

Łukasz Milik

Nowadays, we are facing many problems concerning creating website layouts. Especially when it’s expected that they look good on every type of screen. There are several tools that can help us, like grid systems or open libraries, but what to do when we want to create our own layout using only CSS?

Luckily, there’s a solution for that, too. Oh, wait! Actually, there are two of them: CSS Flexbox and Grid.

What is CSS Flexbox used for?

CSS Flexbox was introduced earlier than its younger brother, CSS Grid. It quickly became the new standard for positioning elements in a container, giving developers the possibility to easily adapt them using media queries.

But how does it work and what makes it special? We can say that CSS Flexbox is content-dependent. It tries to adjust elements to take the optimal space in their container depending on what’s inside of them.

Let’s take a look at some code:

<div class="flexbox__wrapper">

  <div class="flexbox__item">Lorem Ipsum dolor sit amet</div>

  <div class="flexbox__item">1</div>

  <div class="flexbox__item">2</div>

  <div class="flexbox__item">3</div>

  <div class="flexbox__item">4</div>

  <div class="flexbox__item">5</div>

  <div class="flexbox__item">6</div>

  <div class="flexbox__item">7</div>

  <div class="flexbox__item">8</div>

 </div>

.flexbox__wrapper {

  margin: 100px auto;

  width:80%;

  background: #ededed;

  display: flex;

  flex-wrap: wrap;

  flex-direction: row;

  justify-content: center;

}

.flexbox__item {

  background: rgba(0,0,0,0.4);

  border: 2px solid #333;

  padding: 1rem;

  flex: 0 1 auto;

}

We can set the default element width and decide how an element should behave when there is not enough space in the wrapper (or when there’s too much of it).

.flexbox__item {

  background: rgba(0,0,0,0.4);

  border: 2px solid #333;

  padding: 1rem;

  flex: 1 0 150px;

}
Flex grow is set to 1 (with base width set to 150px). When an element is wrapped to a new line, it gets all the available space.

Here’s how it works with flex-grow set to 0:

flex: 0 0 150px;

With flex-grow set to 0, all the elements are taking the flex-basis width (here set to 150px).

Additionally, we can set the position of the elements in relation to each other without any calculations:

justify-content: flex-start;

justify-content: flex-end;

justify-content: space-evenly;

This property has many more variations, giving us plenty of possibilities to rearrange elements as we like.

One more thing to mention, and I think it may be the most important one: CSS Flexbox is one axis-oriented. It means that we can place elements in rows or columns, but not in both directions at the same time.

flex-direction: row;

flex-direction: column;

It’s worth remembering that after changing flex-direction to a column, not only the axis itself will change (from horizontal to vertical), but also all of its corresponding properties. So, for example, flex-basis will work in axis Y.

However, it won’t change the axis of the content itself.

Here, the flex-basis is set to 150px (basically the width), but because we have changed the direction to “column” – it grows on axis Y.

For those of you who are still not convinced that Flexbox is a powerful solution that can be used in a wide variety of cases: what If I tell you that you can reorder your items as you please? And just by giving them ordering numbers!

Let’s take a look at our previous example:

And now, let’s put the last item at the beginning by simply doing this little thing:

.flexbox__item:last-child{

  order:-1

}

Be aware of one important fact, though: the code shown above can be considered an ugly workaround – but it’s here just to show you an example, I hope I will be forgiven.

I did it this way because, by default, all Flexbox elements are ordered with value 0, and they are displayed as source order provided in HTML (as they have the same order value, this is the only way to order them).

Basically, we need to order every element in our container for the ordering to be done right, so that would present like:

.flexbox__item:nth-child(1){

  order:1

}

.flexbox__item:nth-child(2){

  order:2

}

.flexbox__item:nth-child(3){

  order:3

}

.

.

.

.flexbox__item:nth-child(9){

  order:0

}

Which would give exactly the same effect.

I think it’s worth mentioning because ordering behavior can also be controlled by media queries and will help us to adjust the placement of the items as we please.

But which browser likes to cooperate with Flexbox? The answer is all of them, including IE 10 and 11 (with small hiccups, but still). 

We can use Flexbox almost everywhere nowadays. Source: https://caniuse.com

If you happen to have an issue, though, do not despair! The Flexbox community has been struggling with various unexpected issues in different browsers. To help each other, they have created a small Github repo with readme, where you can find a list of such unusual behaviors. They’re nicely described, with fixes and workarounds.

Here’s the link: https://github.com/philipwalton/flexbugs/blob/master/README.md#flexbug-1

What is CSS Grid used for?

On the other hand, we have the CCS Grid layout. Grid is a pretty powerful layout system that enables us to organize the elements as a whole in the desired container.

Here’s how it looks in code:

<div class="grid__layout">

  <header></header>

  <aside></aside>

  <section></section>

  <footer></footer>

</div>

header,aside,section,footer {

  width:100%;

  height: 100%;

  opacity: 0.5;

}

header {

  background: red;

  grid-area: 1/1/2/3

}

aside {

  background: green;

  grid-area: 2/2/3/3

}

section {

  background: blue;

  grid-area: 2/1/3/2

}

footer {

  background: purple;

  grid-area: 3/1/4/3

}

.grid__layout {

  width:100%;

  height:400px;

  background: #ededed;

  display:grid;

  grid-template-columns: 2fr 1fr;

  grid-template-rows: 1fr 2.5fr 1fr

}

It’s worth remembering that the Grid layout system is container-based (opposite to Flexbox, which is content-based). This means that we can control the placement of containers, but we can’t control the placement of the elements inside them.

There’s one small but very useful thing that is possible with Grid but not with Flexbox (well, at least not out of the box), namely – we can put gaps between elements. In Flexbox, we have to use various workarounds to have the desired effect. In Grid, it’s enough to use one short line:

grid-gap: 10px;

And that’s it! No negative margins or invisible borders necessary.

CSS Grid gives us a fluid element system that can provide responsive behavior without using media queries:

<div class="grid__layout">

  <div>first element</div>

  <div> second element</div>

  <div> third element</div>

  <div> fourth element</div>

</div>

.grid__layout {

  width:100%;

  height:400px;

  background: #ededed;

  display:grid;

  grid-gap: 10px;

  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr))

}

.grid__layout > div {

  background: rgba(0,0,0,0.5);

  border: 2px solid #333;

}
The auto-fit property takes care of filling elements in given spaces without a single media query.

Quick note: this only works with the “repeat” column template. In other cases, we still need media queries.

But there’s still so much more that we can do! You already know the Flexbox ordering capabilities – we have something similar in Grid. Or something even better: a very powerful variation of grid-areas. It enables us to name our elements and arrange them in our grid layout using these names.

Here’s how it works:

header,aside,section,footer {

  width:100%;

  height: 100%;

}

header {

  background: rgba(255,0,0, 0.5);

  grid-area: header;

}

aside {

  background: rgba(0, 255, 0, 0.5);

  grid-area: aside;

}

section {

  background: rgba(0,0, 255,0.5);

  grid-area: content;

}

footer {

  background: rgba(156,0,255,0.5);

  grid-area: footer;

}

.grid__layout {

  width:100%;

  height:400px;

  background: #ededed;

  display:grid;

  grid-template-columns: 2fr 1fr;

  grid-template-rows: 1fr 2.5fr 1fr;

  grid-template-areas:"header header"

                    "content aside"

                    "footer footer";

}

This looks exactly the same as our first CSS grid example, but let’s go further – let’s say I want the sidebar to be stretched all the way down to the bottom. Content and footer elements should be exactly the same width. So let’s introduce a small change:

.grid__layout {

  width:100%;

  height:400px;

  background: #ededed;

  display:grid;

  grid-template-columns: 2fr 1fr;

  grid-template-rows: 1fr 2.5fr 1fr;

  grid-template-areas:"header header"

                    "content aside"

                    "footer aside";

}
Aside stretched all the way down with one, very simple change.

It’s super easy and, as you probably already know, it can be used to perform various layout changes in the entire application (with a little help from media queries, of course). Personally, I like this solution a lot more than the Flexbox one since we don’t need to count the grid lines – we can see the “template” right in front of us.

Last but not least, the Grid layout system is two-dimensional. We can place containers in two dimensions, we don’t have to choose just one axis. Basically, we can place our grid elements in any place in the grid, even go beyond the given grid areas:

Our grid is by default divided into two columns. But using grid areas, we can expand elements to fill bigger spaces (like header and footer in this example). Here we can also see how browsers see our grid areas.see

So, can we already use CSS Grid on all browsers? Well, it’s almost there. The important thing to mention here is that Internet Explorer 10 and 11 use an old implementation of this feature (with partial support only). So if you are developing an app for this browser – please check the documentation.

Source: https://caniuse.com

CSS Flexbox vs Grid

Yet the main question is: which is better, CSS Flexbox or Grid? And the answer isn’t obvious, because these two layout systems were created to provide solutions to different types of problems.

I think the best way to put it is:
For managing the main layout of your site – use the Grid layout, but for controlling elements inside of it – use Flexbox.

(Or at least that’s the most logical explanation to me.)

That leads us to the conclusion that we can use both of the layouts at the same time:

<div class="grid__layout">

  <header></header>

  <aside></aside>

  <section>

    <div class="flexbox__wrapper">

  <div class="flexbox__item">Lorem Ipsum dolor sit amet</div>

  <div class="flexbox__item">1</div>

  <div class="flexbox__item">2</div>

  <div class="flexbox__item">3</div>

 </div>

  </section>

  <footer></footer>

</div>

header,aside,section,footer {

  width:100%;

  height: 100%;

  opacity: 0.5;

}

header {

  background: red;

  grid-area: 1/1/2/3

}

aside {

  background: green;

  grid-area: 2/2/3/3

}

section {

  background: blue;

  grid-area: 2/1/3/2

}

footer {

  background: purple;

  grid-area: 3/1/4/3

}


.grid__layout {

  width:100%;

  height:400px;

  background: #ededed;

  display:grid;

  grid-template-columns: 2fr 1fr;

  grid-gap: 10px;

}

.flexbox__wrapper {

  margin: 100px auto;

  width:80%;

  background: #ededed;

  display: flex;

  flex-wrap: wrap;

  flex-direction: row;

  align-content: space-evenly;

}

.flexbox__item {

  background: rgba(0,0,0,0.4);

  border: 2px solid #333;

  padding: 1rem;

  flex: 1 1 auto;

}

I hope this article puts a little light on how Grid and Flexbox are different yet still can work together. It covers the fundamental information, and I’m sure that when you go deeper into the matter, you will find more cases where you can use them separately and others, in which they give the best results when combined.

Rated: 5.0 / 1 opinions
Lukasz Milik cropped f52ae05866

Łukasz Milik

Frontend Developer who loves to play video games but doesn’t mind throwing a K20 dice from time to time as well. He loves to cook and bake, and the gym where he goes to weightlift is his second home. His professional specialty is HTML, CSS, and Angular – and he’s always happy to help, so if you happen to have any questions, don’t hesitate to reach out to him.

Our mission is to accelerate your growth through technology

Contact us

Codete Global
Spółka z ograniczoną odpowiedzialnością

Na Zjeździe 11
30-527 Kraków

NIP (VAT-ID): PL6762460401
REGON: 122745429
KRS: 0000983688

Get in Touch
  • icon facebook
  • icon linkedin
  • icon instagram
  • icon youtube
Offices
  • Kraków

    Na Zjeździe 11
    30-527 Kraków
    Poland

  • Lublin

    Wojciechowska 7E
    20-704 Lublin
    Poland

  • Berlin

    Bouchéstraße 12
    12435 Berlin
    Germany