Simple Flexbox Grid System

bender-grid
… with blackjack, and hookers! (ref)

Introduction and Requirements

A while ago, I created a small and simple flexbox-based grid system for use in the projects we make at work. The developed Grid System inspired upon how Bootstrap works:

  • it divides the grid into 12 columns (configurable).
  • it supports gutters in between columns (configurable).
  • it supports different viewport sizes, linked to keywords:
    XXS, XS, SM, MD, and LG (configurable).
  • it allows columns to adjust size based on the viewport size.
    Eg. .column-xs-12 applies only to the XS layout, .column-md-6 only applies to the MD layout, .column-lg-4
  • it allows offsetting of columns, also reliant upon the viewport size.
    Eg. .offset-md-4, .offset-lg-6.
  • it allows nesting of grids, keeping the defined gutter in place.

Along with that, a few extra requirements/features were added:

  • it must be standalone
  • it must use flexbox – not floats – for layout.
  • it must use em-based units – not px-based units – for sizing (where appropriate).
  • it must support viewport-unreliant column sizing. Eg. .column-8.
  • The columns must fill up the entire width of the wrapper/row. E.g. no (half-)gutter to the left of the first column, and no (half-)gutter to the right of the last column.
  • (added 2016.10.18) it must support auto and stretch columns in case you want to go off-grid

css-flexbox-grid

Demo

Embedded below is the source and the demo pen. The CSS is written in Stylus, our CSS preprocessor of choice.

See the Pen Flexbox Grid by Bramus! (@bramus) on CodePen.

TIP: You might want to check out the pen in a standalone tab/window, so that you can resize it.

How to use

To get started, add .has-columns onto the wrapper. For each column add .column along with one ore more size specifications such as .column-xs-4 and (optional) an offset specification such as .offset-xs-2.

Column size names are based on portions/units. A column .column-xs-4 for example is 4 units of the total of 12 columns, resulting in a column of approximately – depending on the gutter size – 33% in width.

<div class="has-columns">
    <div class="column column-xs-4">.column-xs-4</div>
    <div class="column column-xs-4">.column-xs-4</div>
    <div class="column column-xs-4">.column-xs-4</div>
</div>

See the pen embedded above for some examples.

Columns with the classname .column-auto will not take up a given portion, but will only take up the space their content requires. This kind of column is typically used in combination with a column .column-stretch. An example would be for a message-component that consists of an avatar and a content:

<div class="message">
    <div class="has-columns">
        <div class="column column-auto">
            <img class="message__avatar" src="avatar.png" alt="" title="" />
        </div>
        <div class="column column-stretch">
            <div class="message__text">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
        </div>
    </div>
</div>

How it works

tl;dr: the width of each column is adjusted – using calc() – to take the defined gutter into account.

Say you have 2 columns that you want to display, each being 6 units wide (e.g .column-6). We can safely state that their base-width is 6/12, or 50% each.

<div class="has-columns">
    <div class="column column-6">.column-6</div>
    <div class="column column-6">.column-6</div>
</div>

In between those two columns a gutter of 1em is injected, using margin-right on the first column. There’s no gutter to the left of the first column, nor to the right of the second column (put differently: all columns, except for the last one, get a gutter applied using margin-right).

Given our 2 columns of 50% width each, this yields of a combined width that exceeds 100%: 50% (base-width) + 1em (gutter) + 50% (base-width) + 0em (no gutter for the last column!) = 100% + 1em = too wide.

css-grid-notadjusted
Columns without adjusted width = too wide

To not exceed 100%, the actual width of our columns need to be adjusted by (in this case) -0.5em each, neutralizing the 1em gutter in between. With the adjustment applied, this yields a combined width of exactly 100%: 50% (base width) – 0.5em (adjustment) + 1em (gutter) + 50% (base width) – 0.5em (adjustment) + 0em (no gutter for the last column!).

css-grid-adjusted
Columns with adjusted width= perfect fit

For 3 columns (each being 4 units wide, or 4/12, or 33.3333% base-width each) a total gutter worth of 2em is injected. The adjustement for these 3 columns therefore is 0.666666667em.

If one would derive a formula to calculate the $gutterAdjustmentPerColumn, it’s this:

$gutterAdjustmentPerColumn = $gutterSize * (1 - ($columnWidthInUnits / $totalNumberOfColumns))

The same logic – albeit a tad different – is used to calculate the $offsetAdjustmentPerColumn

Simple Flexbox Grid System →

Fukol™ Grids

fukol-demo

Building a CSS Grid System isn’t that hard really, thanks to flexbox. Heydon has stripped it to its smallest form:

.fukol-grid {
  display: flex;
  flex-wrap: wrap;
  margin: -0.5em;
}

.fukol-grid > * {
  flex: 1 0 10em;
  margin: 0.5em;
}

Fukol™ is a lightweight, breakpoint free, completely responsive, element query driven*, progressive enhancement based CSS grid framework. It is 93 bytes minified, fitting comfortably inside a tweet.

Embeded below is a demo pen:

See the Pen Fukol by Heydon (@heydon) on CodePen.

Fukol™ Grids →

Flexbugs – Flexbox issues and cross-browser workarounds for them.

flexbugs

This repository is a community-curated list of flexbox issues and cross-browser workarounds for them. The goal is that if you’re building a website using flexbox and something isn’t working as you’d expect, you can find the solution here.

Truth be told, most of the time “something is not as I’d expect” when using flexbox 😛

philipwalton/flexbugs →

Quantity Ordering With CSS

Here is your mission, should you choose to accept it: create a table of items. Each item should span a third of the content area, with the fourth item starting on a new row, much like floats. However, a particular item must always display the price at the end of the first row.

Visually, we want to achieve this:

css-quantity-ordering

Note the blueish item with the green outline at the end of the first row. Even though it’s declared last in in the HTML, it’s positioned at the end of the first row, no matter how many other elements the list holds. Using quantity selectors and Flexbox’ order property, the CSS needed to achieve this is:

// Note: outline added for visual reference

// All items: Set the order to 1.
// Note: Items that have the same CSS `order` value will appear in the order as they are declared in the HTML.
.container .item {
  order: 1; /* This is the default, no need to explicitly declare it */
  outline: 1px solid blue;
}

// If there are more than 3 items, set the CSS order of that third item and its successive items to 3. That way a tiny gap in the CSS order sequence is created.
.container .item:nth-child(n+3) {
  order: 3;
  outline: 1px solid red;
}

// If there are more than 3 items, move .time in between the first two and all other items by setting the CSS order to 2. That way it'll squeeze in between the items with CSS order 1 and CSS order 3, giving us the wanted result
.container .item:nth-last-child(n+3) ~ .time {
  order: 2;
  outline: 1px solid lime;
}

Here’s the resulting pen:

Check out this Pen!

Quantity Ordering With CSS →

Flexbox adventures

Up until reading Flexbox Adventures I hadn’t really given much thought to how flexbox grow exactly works. If you do want to know:

Available space = (Container size – Flex-basis siblings total).

Flex Item size = Basis + ((Available space / Total Grow nums) * Individual grow num).

A recommended read.

Flexbox adventures →

When working with flexbox, I always find myself ending up at A Complete Guide To Flexbox

Dive into Flexbox

Flexbox is a new layout mode in CSS3 that is designed for the more sophisticated needs of the modern web. This article will describe the newly-stablized Flexbox syntax in technical detail.

Great to see that after three years it has become a candidate recommendation. Time to start digging a grave for faux columns (née 2004) and all vertical css centering articles.

Dive into Flexbox →