Rethinking the Grid

At Shopify, we’re rebuilding much of our front-end code for Shopify Admin. This is giving us the opportunity to re-evaluate why and how we build things.

One of the first components that we decided to work on was the grid.

24 Column Grid

Shopify has, for at least the last two and a half years that I’ve worked there, a 24 column, percentage-based grid. This type of grid is quite common in the industry and one that many designers like.

As we talked about what our new grid system should be, some designers on our team pushed to keep the 24 column grid that we already had. Predictable, flexible, and familiar.

Code Audits

I did an audit of how many of those twenty-four span classes were being used and perhaps unsurprisingly, a fourth of them were unused.

Another fourth of the classes were used only a handful of times.

These types of code audits are very useful because they help reveal opportunities for optimization.

I’m not a fan of creating code on the off-chance that it might be used someday. The code audit revealed that we could lighten our load.

Making it easier for everybody

One of the goals was to have a system that was easy for designers and developers alike. If a new cell is added in a row, the design shouldn’t just fall apart.

Looking at the design, we noticed that most of the time, we just needed cells of equal width.

With Shopify Admin, our browser support is kept to modern browsers and with that came quick consensus among the team: “let’s try flexbox!”

We let flex-grow do its magic. Cells become equal width and new cells can be added without breaking the design.

.grid { display: flex; }
.grid__cell { flex: 1; }

Not every row is going to have equal width cells, though, and this is where we ran into some contention on the team.

My original proposal was to use flex-grow to achieve cells of different weights. flex-grow: 2 in a row of 3 cells would produce one cell at 50% width and the others at 25%.

This had a couple limitations, though:

  1. It didn’t allow a lone cell in a row to be less than 100%, and
  2. padding throws off cell calculations for which box-sizing doesn’t help. (`flex-basis` solves the padding issue.)

We decided to augment our system with a few percentage-based classes: .grid__cell--half, --third, --quarter, and --fifth. This solved the two limitations we had with the previous approach and works well with the default .grid__cell.

.grid__cell--half    { flex: 0 0 50%; }
.grid__cell--third   { flex: 0 0 33.333%; }
.grid__cell--quarter { flex: 0 0 25%; }
.grid__cell--fifth   { flex: 0 0 20%; }

What’s next

We’ve created the grid but have yet to roll it out across the site—and deal with any of the unforeseen issues that may come out of this approach.

Right now, it looks like flexbox will give us a flexible (pun unintended) system with less code. That’s a win-win.

Published August 09, 2014
Categorized as HTML and CSS
Short URL:


15 Comments · RSS feed
Giuseppe Gurgone said on August 10, 2014

This look very simple and neat. I love it!

With Shopify Admin, our browser support is kept to modern browsers and with that came quick consensus among the team: “let’s try flexbox!”

You lucky b******s! :D

I've been advocating simple grid systems (canonical layouts actually) at work and a while ago I open sourced something similar.
It is not as cool as if it were implemented with flexbox but you know... backward compatibility.

Mike Aparicio said on August 10, 2014

I've been running into the same thing and have been experimenting with a more simple flexbox grid. Here's what I came up with so far:

Jonathan Snook said on August 11, 2014

Our intention isn't to use the grid for full page layout, just the inner grid.

Jérôme Coupé said on August 11, 2014

Thanks for the clarification. Looking forward to see this in action. Loving the new Shopify, BTW.

Paul Howells said on August 11, 2014

Another way to reduce unused grid code (that can also be used with the approach in this article) is to use preprocessing (e.g. Less or Sass), define the .grid classes as mixins, and use the mixins within SMACSS layout selectors as needed.

The unused mixins won’t appear in the final CSS. The downside of course is – the ever present danger of using a mixin instead of a class – a larger CSS file due to repetition.

Martijn said on August 12, 2014

Unfortunately, this will only work on a handful of browsers, among which are NOT all the modern ones. Firefox still has some serious problems with the flexbox model, the biggest of which is that it can't wrap. So you'll always end up with a single row of cells, no matter what.

I believe Chrome and IE11 have much fewer problems, but I'm sure each has at least a few problems to work around.

Martijn said on August 12, 2014 if your goal is to make a webapp for Windows 8 Metro, or a webapp for any guaranteed-WebKit/Blink based platform, go right ahead :)

(trying to give my previous comment a bit of a positive wirl)

jerry said on August 15, 2014

As some others have already mentioned, I find it odd that you're using the flexbox model which has very limited compatibility. Is that not a concern?

Jonathan Snook said on August 15, 2014

As mentioned in the post, we support modern browsers that support flexbox and we're using it to solve very specific problems for which flexbox will work well for our needs. If you have different requirements and flexbox doesn't meet those requirements then use something else.

Paolo Chiodi said on August 17, 2014

I came across and really liked the approach of not having a proper grid, but a way to lay out the elements in a grid while setting widths on the single elements.
I complemented this with a couple of sass functions that calculate the percentage width and margin based on the number of column to span and skip (and the container with, allowing for nested grid)
What is your thinking?

Toby Evans said on August 17, 2014

Firefox supported flex-wrap for a few versions now(29 I think).
I’ve been using flexbox successfully with IE10 up with very few problems.
The real issues are that there is no way to select edge elements. I’d like to see some psedo selectors like :start-edge, :end-edge, :first-row, :last-row - or something to that effect.

Chris Lake said on August 20, 2014

Having just gone through an intensive admin refresh based around Foundation's grid (, I'll be *very* interested to hear your thoughts after you've rolled it out across the site.... The "unforeseen issues" you mention imo being the deciding factor in judging the relative success of *any* approach.

DOGUKAN GUVEN NOMAK said on August 21, 2014

check out :)

Paul Lynn said on August 21, 2014

how about this?
i think its quite easy to use and doesn't need any classes in the markup.

Gluck666 said on November 03, 2014

Doesn't work in IE

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.

Want to learn about scaling CSS for large projects?

I'm available for full and half-day workshops on scalable CSS architecture. I can provide on-site training for your team. Interested?
Get in touch.