DEV Community

loading...
Cover image for Equal Height Elements: Flexbox vs. Grid

Equal Height Elements: Flexbox vs. Grid

Stephanie Eckles
(she/her) ✍️ ModernCSS.dev, πŸ‘©πŸΌβ€πŸŽ¨ StyleStage.dev, πŸ‘©β€πŸ’» Software Engineer, πŸ‘©β€πŸ« @eggheadio instructor, πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘§ mom
Originally published at moderncss.dev ・Updated on ・2 min read

This is the second post in a series examining modern CSS solutions to problems I've been solving over the last 13+ years of being a frontend developer. Visit ModernCSS.dev to view the whole series and additional resources.

Once upon a time (approximately 7 years ago), I wrote a jQuery plugin to calculate equal height columns. It ensured that the very specific scenario of a row with three columns would keep the content boxes equal height no matter the length of the content they contained. The dominant layout method at the time - floats - did not handle this problem.


Flexbox Solution

When flexbox arrived on the scene, this became possible with:

.flexbox {
  display: flex;
}
Enter fullscreen mode Exit fullscreen mode

Amazing! By default, direct children line up in a row and have a "stretch" applied so they are equal height πŸ™Œ

But then you add two .column divs as children and... the contents of the columns appear unequal again πŸ˜”

The fix is:

.flexbox {
  display: flex;

  // Ensure content elements fill up the .column
  .element {
    height: 100%;
  }
}
Enter fullscreen mode Exit fullscreen mode

Now the columns will appear equal height and grow with the content of .element.

Grid Solution

With grid, we encounter similar behavior:

.grid {
  display: grid;
  // Essentially switch the default axis
  grid-auto-flow: column;
}
Enter fullscreen mode Exit fullscreen mode

Similar to flexbox, direct children will be equal height, but their children need the height definition added just like in the flexbox solution:

.grid {
  display: grid;
  grid-auto-flow: column;

  // Ensure content elements fill up the .column
  .element {
    height: 100%;
  }
}
Enter fullscreen mode Exit fullscreen mode

Here's a demo of both solutions, as well as additional demos for defining a set amount of columns per row as described below:

Which is Better?

For purely solving for equal height elements, the advantage of flexbox is the default axis immediately enables side-by-side columns, whereas grid needs to be explicitly set. However, elements will not inherently be equal-width as well (which may be an advantage depending on type of content, for example navigation links).

The advantage of grid is inherently equal-width elements if that is desirable. An additional advantage is when you don't want auto-flow but instead want to define a set max number of columns per "row". In this case, grid layout easily handles the math to distribute the columns vs. a flexbox solution requiring defining the calculation to restrict the number of columns.

Updating our .grid solution to handle for defining a max number of 3 .column per row is as simple as:

&.col-3 {
  grid-gap: $col_gap;
  grid-template-columns: repeat(3, 1fr);
}
Enter fullscreen mode Exit fullscreen mode

Whereas one (very basic) option for flexbox would be:

$col_gap: 1rem;

.flexbox.col-3 {
  // Explicitly needs to be defined to wrap 
  // overflow items to the next virtual row
  flex-wrap: wrap;

  .column {
    // "hack" for no gap property
    margin: $col_gap/2;
    // define calculation for browser to use on the width
    max-width: calc((100% / 3) - #{$col_gap});
  }
}
Enter fullscreen mode Exit fullscreen mode

You would also need to consider how these solutions are handled responsively, but that's a bit out of scope of this article :)

Discussion (0)