Grid for layout, Flexbox for components – Ahmad Shadeed


0

My brother is a fresh computer engineering graduate and he is currently finishing his internship in front-end development. He learned about both CSS grid and flexbox, but I noticed a pattern that I see a lot on the web. He can’t decide when to use grid or flexbox. For example, he used CSS grid to layout a website header and mentioned that the process wasn’t smooth as he played with grid-column and tried to fine-tune it until it looks like the design.

To be honest, I don’t like that, and I also researched about a resource that he can use to learn the differences between grid and flexbox, with examples on both, but I couldn’t find any. I decided to write an in-depth article that covers everything about that topic. I hope you found it clear!

Introduction

Before diving into concepts and examples, I want to make sure that you understand the main difference between CSS grid and flexbox. CSS Grid is a multi-dimension layout module, which means that it has columns and rows. Flexbox can lay out its child items either as columns or rows, but not both.

If you don’t know about CSS grid and flexbox, I recommend reading this visual article by yours truly. If you know them, that’s cool, let’s dive into differentiating between them, and when to use each one and why.

The Difference Between Grid and Flexbox

Let me be clear about that, there is no direct way to decide between CSS grid and flexbox. Adding on that, there is no correct or incorrect way to use them. This article is a kind of guide that recommends using a technique for a specific use-case. I will explain the general concept, and then go into examples, and the rest is on you to explore and experiment more.

/* Flexbox wrapper */
.wrapper {
    display: flex;
}
/* Grid wrapper */
.wrapper {
    display: grid;
    grid-template-columns: 2fr 1fr;
    grid-gap: 16px;
}

Did you notice something? Flexbox is laying out an inline list of elements, while CSS grid made them a grid of columns and rows. Flexbox is aligning the alignment in a row. That can be a column if we want.

/* Flexbox wrapper */
.wrapper {
    display: flex;
    flex-direction: column;
}

How To Decide Which To Use

Deciding between CSS grid and flexbox can be a bit hard (sometimes), especially if you are new to CSS. I can hear you! Here are some initial kick-off questions that I ask myself when choosing between them:

  • How the component child items are displayed? Inline or as columns and rows?
  • How the component is expected to work on various screen sizes?

Most of the time, if the component you are viewing has all of its child items displayed inline, then most probably flexbox is the best solution here. Consider the following example:

However, if you see columns and rows, then CSS grid is the solution for your case.

Now that I explained the main difference between them, let’s move on to more specific examples and learn how to decide.

Use Cases and Examples

In the following section, I will discuss in detail about different use-cases for both flexbox and grid.

CSS Grid

Main and Sidebar

When you have a sidebar and main, CSS grid is a perfect solution for building them. Consider the following mockup:

Here is how I would do this in CSS:

 class="wrapper">
    
    
Main
@media (min-width: 800px) {
    .wrapper {
        display: grid;
        grid-template-columns: 200px 1fr;
        grid-gap: 16px;
    }
    aside {
        align-self: start;
    }
}

If align-self weren’t used for the

@media (min-width: 500px) {
    .wrapper {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
        grid-gap: 16px;
    }
}
.card {
    display: flex; /* [1] */
    flex-direction: column; /* [2] */
}
.card__content {
    flex-grow: 1; /* [3] */
    display: flex; /* [4] */
    flex-direction: column;
}
.card__link {
    margin-top: auto; /* [5] */
}

Let me explain the CSS above.

  1. Making the card as a flexbox wrapper.
  2. The direction is column, which means the card elements are stacked.
  3. Letting the card content expand and fill the remaining space.
  4. Making the card content as a flexbox wrapper.
  5. Finally, using margin-top: auto to push the link down. This will keep it positioned at the end regardless of the card height.

As you saw, combining CSS grid and flexbox isn’t hard. These two tools can give us many ways to implement layouts on the web. Let’s use them correctly, and combine them only when needed as above.

Fallback and Supporting Old Browsers

Using CSS @supports

A couple of months ago, I got a tweet saying that my website is broken in IE11. After checking it, I noticed a very weird behavior. All the website content is collapsed into the top left area. My website wasn’t usable!

Yes, this is my website – a front-end developer website, on IE11. At first, I was confused, why is that happening? I remembered that CSS grid is supported in IE11, but that’s the old version of it that was released by Microsoft. The solution is very simple, which is to use @supports to only use CSS grid for new browsers.

@supports (grid-area: auto) {
    body {
        display: grid;
    }
}

Let me explain it. I used grid-area because it’s supported only in the new CSS grid spec, from March 2017 till today. Since IE doesn’t support @supports query, the whole rule will be ignored. As a result, the new CSS grid will be used for supporting browsers only.

Using Flexbox as a Fallback For CSS Grid

If flexbox is not suitable for displaying a grid of items, that doesn’t mean it’s not good for fallback. You can use flexbox as a fallback for CSS grid for non-supporting browsers. I worked on a tool that does exactly that.

@mixin grid() {
  display: flex;
  flex-wrap: wrap;
  @supports (grid-area: auto) {
    display: grid;
    grid-gap: 16px 16px;
  }
}
@mixin gridAuto() {
  margin-left: -16px;
  > * {
    margin-bottom: 16px;
    margin-left: 16px;
  }
  @media (min-width: 320px) {
    > * {
      width: calc((99% / #{2}) - 16px);
      flex: 0 0 calc((99% / #{2}) - 16px);
    }
  }
  @media (min-width: 768px) {
    > * {
      width: calc((99% / #{3}) - 16px);
      flex: 0 0 calc((99% / #{3}) - 16px);
    }
  }
  @supports (grid-area: auto) {
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    margin-left: 0;
    > * {
      width: auto;
      margin-left: 0;
      margin-bottom: 0;
    }
  }
}

The fallback code above works as below:

  1. Add display: flex and flex-wrap: wrap to the wrapper element.
  2. Checks if CSS grid is supported, if yes, then display: grid will be used instead.
  3. By using the selector > *, we can select the direct child elements of the wrapper. Upon selecting them, we can add a specific width or size to each one.
  4. Of course, the margin between each one is needed and will be replaced with grid-gap in case CSS grid is supported.

Here is an example of how to use the Sass mixin.

.wrapper {
  @include grid();
  @include gridAuto();
}

Demo

When things go wrong for both grid and flexbox

As I was doing a code review for my brother, I noticed a couple of incorrect uses for either CSS grid or flexbox and I thought that it might be useful if I highlighted some of them.

One of the motivations for this article was this mistake. I noticed that my brother is using CSS grid to implement a website header.

He mentioned things like “it was complex, css grid is hard.. etc”. As a result of using an incorrect layout method, he got an idea that CSS grid is complex. It’s not, and all of his confusion came from the fact of using it for something that is not suitable.

Consider the following example that I noticed.

.site-header {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
}
.site-nav {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
}

CSS grid was used twice, the first time is for the whole header, and the second one is for the navigation. He used grid-column to fine-tune the spacing between the elements, and other weird things that I can’t remember, but you got the point!

Using CSS Grid for tabs

Another incorrect usage for CSS grid is applying it on a tabs component. Consider the following mockup.

The incorrect CSS code looks like this:

.tabs-wrapper {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
}

From the code above, I can see that the developer assumed the tabs count is only three. As a result, he used 1fr 1fr 1fr for laying out the columns. This can easily break if the columns count changed.

Overusing Flexbox or Grid

Remember that old layout method might be perfect for the job. Overusing flexbox or grid can increase the complexity of your CSS by time. I don’t mean they are complex, but using them correctly and in the right context as explained from the examples in this article is much better.

For example, you have the following hero section with a request to horizontal center all the content of it.

This can be done by using text-align: center. Why using flexbox when there is an easier solution?

Conclusion

Phew, that was a lot about the differences between using CSS grid and flexbox. That topic was in mind for a long time, and I’m glad that I got the chance to write about it. Please don’t hesitate to provide feedback either by email or twitter @shadeed9!

Thank you for reading.

Tweet Share Pin it Share Share Share

Like it? Share with your friends!

0
admin