Aligning last child in Flexbox “Grid”

January 3, 2017

I was recently building a site for an architecture firm. The design called for a projects listing page that was a three-column grid. Building with a mobile-first approach, the initial layout is one-column and then a two-column grid starts at 480 pixels. This transitions into a three-column grid at a larger tablet size. The mockup called for the listing layout to center at a width of 940 pixels.

The mockup included a filter navigation so projects could be viewed be pre-defined categories. My default build included a filter navigation that would take the user to a new page. On top of that, I built an enhanced version using JavaScript to filter that page without a page refresh.

After considering several options on how to build the grid, I chose Flexbox as a solution. I wanted to take advantage of Flexbox’s space-between to space out my project listings so that I would not have to apply any margins. I had tried a solution with floated elements with margin on the second and third element in each row and clearing the first element in each row. But the layout would break when I applied the filtering functionality.

Disclaimer: Flexbox is not really the right solution for building grids. As Rachel Andrew explains:

Flexbox is essentially for laying out items in a single dimension – in a row OR a column. Grid is for layout of items in two dimensions – rows AND columns.

Problem

The problem I ran into was when the last row of the grid only had two items, the last item would align to the right side of the grid and not in the middle as you would expect in a grid.

See example on CodePen

In order to build a “grid” in Flexbox, you need to use flex-wrap:wrap to get the content to start a new row. To get the spacing around the elements without using any margin declarations, I used justify-content:space-between. This causes the last item to shift to the right if there are only two items in the row. This is not a failing on the part of Flexbox if you understand that it is for laying out a single dimension, a row or column.

To create the grid, I add Flexbox code to my container which has a class of “project-listing.”


.project-listing {
    display:flex;
    flex-direction:row;
    justify-content: space-between;
    flex-wrap: wrap;
}

Each individual project has a containing div with a class of “project.” I added a width declaration to those elements at the breakpoints where the layout changes to a two-column grid and then a three-column grid.


@media (min-width: 30em) {
    .project {
        width:48.38%;
    }
}

@media (min-width:48em) {
    .project {
        width:31.91%;
    }
}

Looking for solutions

I was sure the others have encountered this same problem and needed a solution that worked with dynamic content. I found a couple of solutions that used generated content(::before or ::after) that pushed the last child into the correct position but those solutions did not work for me. There was one that came close (http://codepen.io/DanAndreasson/pen/ZQXLXj) but it did not have the spacing I needed between the previous element and the last child.


.project-listing::after {
    content: "";
    flex: auto;
}

How to get last child in two-item to display like you would expect in a grid

I thought the generated content was a good approach so I did some experimenting and came up with another solution that gave me the correct spacing between elements.


@media (min-width: 30em) {
    .project::after {
        content:"";
        display: block;
	margin-left: 48.38%;
    }
}

@media (min-width:48em) {
    .project {
        margin-left: 31.91%;
    }
}

The final solution was to put a left margin on the generated content that equaled the size of the project elements. And the generated content did not break the layout when there was just one item or three items on the last row.

See final solution on CodePen

See the Pen Flexbox “Grid” by Jeff Bridgforth (@webcraftsman) on CodePen.

Know When to Break the Rules

It is always important to know your tools and to understand the problems that they were created to fix. Flexbox is the right solution when you are trying to solve a one-dimensional problem, in a row or column. I have used Flexbox solution in site navigation (row) to center and put space between nav items and I have used Flexbox for ordering in mobile views (column).

With that said, I decided to use Flexbox for my “grid” solution because:

  • it involved the smallest amount of code
  • provided flexibility across breakpoints
  • Flexbox allowed me to space out the listing items without having to apply margin
  • Flexbox had wide enough support and I was able to implement a fallback solution in browsers that did not support it
  • I could not yet take advantage of CSS Grid Layout

The better you know your tools, the better-informed decisions you can make as you implement solutions. I was able to find a solution to make Flexbox work but that may not always be the case. I chose to use Flexbox because it was the best solution I could find to solve my problem today.

Looking to the future

An even better solution adds support for CSS Grid Layout so it will work in the future when it is implemented in the browsers (which will hopefully happen in February or March). Using feature queries, we can add code today that browsers will support tomorrow.


@supports (display: grid) {
    @media (min-width:$break-2) {
        .project-listing {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            grid-column-gap:18px;
            grid-row-gap:18px;
        }
        .project-listing::after {
            display:none;
        }
        .project {
            margin-bottom:0;
            width:auto;
        }
    }
    @media (min-width:$break-4) {
        .project-listing {
            grid-template-columns: repeat(3, 1fr);
        }
    }
}

See feature query solution on CodePen

Resources

If you are interested in finding out more about CSS Grid Layout, I suggest checking out Grid By Example by Rachel Andrews. I went through the tutorial videos a couple of weeks ago. The tutorials have equipped me to hit the ground running and begin using Grid Layout with feature queries right away.

If you are interested in finding out more about feature queries, I suggest an article written by Jen Simmons. I would also encourage you to check out her experimental layout lab.

4 Comments

  1. H Max

    March 1st, 2017

    Good info, thanks.

  2. Arthur

    June 23rd, 2017

    You are the best!

  3. David

    November 11th, 2017

    Nice solution, thanks.

  4. Justinas

    December 28th, 2017

    Thanks! That’s a great solution.