A Flexy Little Grid System

A super tiny and stupid simple flexbox grid mixin.

Flexbox Grid Mixin

Here at Pigeon Wisdom, we’ve been using flexbox on client work for about a year now. In that time, we’ve learned a great deal about the spec, where it shines, and perhaps more importantly, where it flounders.

For staters, it’s not the layout golden ticket heralded by so many before it dropped. But, if you’re aware of its limitations and proper use, flexbox can result in much cleaner, and far less, code.

Grids on the Parent

Most flexbox grid systems currently in the wild are essentially updated versions of the whole float-based 12 columns thing, with flex-basis replacing width. And that’s cool. We’ve adapted our own tried-and-true grid in a similar fashion.

However, in moving towards BEM syntax and more modular / component-based builds, our use of grid helper classes has significantly diminished. This especially rings true when dealing with CMS generated content with unknown child elements – a pattern common to all of our builds these days. Instead, we’ve been rocking a handy little flexbox mixin that’s applied directly to grid containers.

The Mixin


//----------------------------------------------  
//  flex-grid();
//  Creates grid blocks via flexbox

//  @param: $sm, $med, $lg, $xl - @media sizes
//  @param: $pad  - item padding  
//  @useage: @include g-blocks(1, 2, 3, 4, 0.5em);
//----------------------------------------------
@mixin flex-grid($sm:null, $med:null, $lg:null, $xl:null, $pad:0) {
  display: flex;
  flex-direction: row;
  flex-flow: wrap;
  margin-left: -$pad;
  margin-right: -$pad;
  list-style: none;

  & > * {
    padding: $pad;
    flex-basis: 100%/$sm;
    max-width: 100%/$sm;
    
    @media (min-width: $mq-med) {
      flex-basis: 100%/$med;
      max-width: 100%/$med;
    }

    @if $lg {
      @media (min-width: $mq-large) {
        flex-basis: 100%/$lg;
        max-width: 100%/$lg;
      }
    }

    @if $xl {
      @media (min-width: $mq-xlarge) {
        flex-basis: 100%/$xl;
        max-width: 100%/$xl;
      }
    }
  }
}

//----------------------------------------------  
//  Media Queries
//----------------------------------------------
$mq-small: 32em;
$mq-med: 54em;
$mq-large: 65em;
$mq-xlarge: 91em;

Usage

The mixin itself takes 5 arguments – The first 4 relate to the number of columns across 4 breakpoints (sm, med, lg, xl), and the last applies column padding. The arguments are optional, so you can add just what you need without generating any extra output. As you can see, we’re using the universal selector so you can apply the grid to any parent, without having to alter your column classes – ideal for BEM syntax.

For the following examples, lets say we have a parent class called .blocks, with childs named .blocks__item (though, the child name is irrelevant). Here are a few grid possibilities:

1 column at sm, 2 at med, 3 at lg, 4 at xl, with 0.5em of padding:

.blocks{
  @include g-blocks(1, 2, 3, 4, $pad:0.5em);
}

2 columns at sm, 3 at med, 4 at lg, with 0.5em of padding:


.blocks {
  @include g-blocks(2, 3, 4, $pad:0.5em);
}

1 column at small, 3 at medium, with 1em of padding:


.blocks {
  @include g-blocks(1, 3, $pad:1em);
}

You get the idea.

Here’s a little demo of the mixin in action, and you can also snag the code on Github

Flexbox Caveats

While flexbox is well supported now, there are plenty of browser related issues that you’ll encounter. Here are a few that we’ve run into:

  • Firefox – no percentage paddings
    While all other browsers respect percentage paddings/margins in a flex layout, Firefox won’t play ball. Admittedly, this interpretation of the spec is not incorrect, but it still sucks and Mozilla’s Daniel Holbert has been a tad indignant on the matter, after enjoying an onslaught of bug reports. Amusingly, homie went so far as to file a Chrome bug report (do you playa).

    I’d argue that the spec should be revised regarding this matter, and luckily, the W3C working group is currently taking it under consideration.

    Sadly, no percentages also means no instrinsic-ratio, padding-bottom moves, unless you nest. Lame.

  • More Firefox woes

    For some reason, Firefox needs a min-height and min-width applied to flex elements. We’ve solved this with the following:

    
    // Firefox flexbox fix
    * {
      min-width: 0;
      min-height: 0;
    }
  • IE Needs a backup for Flex-basis percentage sizing, namely max-width.
    On IE, flex-basis often isn’t enough. So, add an additional max-width of the same percentage.
  • WTF align-self?
    Align-self is unpredictable. Sometimes it works, sometimes not so much. Still have to sit down and figure out the specifics on this.

More on Flex

For more on flexbox bugs and fixes, check out Philip Walton’s Flexbugs community collection repo.

Learn more about the spec here.

For a complete guide to Flexbox, check this CSS Tricks article.

Demo & Downloads

Demo

Github

For UI e-mail awesomeness