Go Back

How to Create a Flawless Responsive Post Grid with Flexbox

Author: Ben Bozzay

Today we’ll learn the best way to create a grid to easily display content, like Wordpress posts, with minimal media queries required for the responsive views.

We frequently see websites using a multi-row setup to organize similar content:

<div class="row">
  <div class="col">
    ...
  </div>
  <div class="col">
    ...
  </div>
</div>
<!--next row-->
<div class="row">
  <div class="col">
    ...
  </div>
  <div class="col">
    ...
  </div>
</div>

Using multiple rows complicates the responsive layout significantly:

Two rows with 5 columns in each rowTwo rows with 5 columns in each row

Notice how extra whitespace is created in responsive views due to columns being separated into rows. The columns don’t fill up the remaining space, so some screen sizes have an odd looking whitespace.

On mobile, some columns appear to have a bigger vertical whitespace because of the row’s margin-bottom. This looks sloppy!

We could adjust the media queries for the rows and columns, but this requires a lot of tweaking to get right.

Using flexbox, we can easily create a responsive grid:

*View the codepen for this grid.

In many situations, you’d want to use Ajax-load-more or filters to dynamically display content on a page, so a grid-layout would be needed.

For example, as part of our web presence overhaul for {code}, Open Source at Dell Technologies, we created a page for dynamically displaying posts based on filter and sorting options.

We created a grid layout so that posts could easily be appended without breaking the layout. In this tutorial, you’ll learn how to re-create this post grid.

Creating the responsive grid

Making the grid items responsive is easy using Flexbox.

Let’s examine the wrapping elements:

... All of our grid-items (columns) are wrapped with one row and one container.
.container {
  max-width: 1335px;
  margin: 0 auto;
}
.grid-row {
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
}

Our container CSS sets the total max-width. Using display: flex, our grid-row stretches to the full size of the container.

We use flex-flow: wrap to designate that child divs (our columns/grid-items) should wrap if they exceed the width of the row. Then, flex-flow: row means our grid-items will flex from left to right. If we used flex-flow: column, our child divs would flex from top down.

*Source: https://css-tricks.com/almanac/properties/j/justify-content/`

Then, we use justify-content: flex-start because we want our grid-items to line up next to each-other at the start of the row.

Creating the grid item

Each grid-item should have identical height, so we set a height of 550px:

.grid-item {
  height: 550px;
  flex-basis: 20%;
  -ms-flex: auto;
  width: 259px;
  position: relative;
  padding: 10px;
  box-sizing: border-box;
}

On desktop views, we set a flex-basis of 20% for each grid-item. This means that 5 grid-items will display on the same level. The 6th grid-item will wrap to the next “row” since we are using flex-wrap: wrap in our grid-row.

We set a width of 259px for certain browsers that require a width to be defined. However, the actual width is set by flex-basis.

Media Queries

We only need a few media queries on our .grid-item. We just need to define the flex-basis on each desired screen-width.

Based on the content within our grid-items, we used these media queries:

.grid-item {
  height: 550px;
  flex-basis: 20%;
  -ms-flex: auto;
  width: 259px;
  position: relative;
  padding: 10px;
  box-sizing: border-box;
}
@media(max-width: 1073px) {
   .grid-item {
    flex-basis: 33.33%;
  }
}
@media(max-width: 815px) {
  .grid-item {
    flex-basis: 50%;
  }
}
@media(max-width: 555px) {
  .grid-item {
    flex-basis: 100%;
  }
}

On the smallest screen-width, we use a flex-basis of 100% to make our grid-item the full-width of the grid-row.

If you’re building for mobile-first, you should adjust your CSS this way:

.grid-item {
  height: 550px;
  flex-basis: 100%;
  -ms-flex: auto;
  width: 259px;
  position: relative;
  padding: 10px;
  box-sizing: border-box;
}
@media(min-width: 1073px) {
  .grid-item {
    flex-basis: 33.33%;
  }
}
@media(min-width: 815px) {
  .grid-item {
    flex-basis: 50%;
  }
}

Our .grid-item defaults to a flex-basis of 100% unless the screen size is a large tablet or a laptop/desktop.

With either approach, we only need to change the flex-basis for a few screen-widths to achieve a grid.

Cross-browser support

The CSS in this tutorial doesn’t cover all of the vendor prefixes required when using flexbox. If you’re using a build tool like Webpack or Vite, make sure you use PostCSS with autoprefixer to automatically add all the required vendor prefixes to your compiled CSS files.

If you aren't using any tooling, you can also generate these vendor prefixes by pasting your CSS into an autoprefixer tool like this one.

Finishing up

View the full source code, which also includes the styles for the content in each grid-item and the hover/grow effects.