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:
- It didn’t allow a lone cell in a row to be less than 100%, and
- 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.
Conversation
This look very simple and neat. I love it!
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.
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: http://codepen.io/peruvianidol/pen/EwGxq
Our intention isn't to use the grid for full page layout, just the inner grid.
Thanks for the clarification. Looking forward to see this in action. Loving the new Shopify, BTW.
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.
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.
...so 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)
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?
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.
I came across http://arnaudleray.github.io/pocketgrid/ 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?
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.
Having just gone through an intensive admin refresh based around Foundation's grid (http://foundation.zurb.com/grid.html), 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.
check out :) http://flexible.gs
how about this? https://github.com/goodpixels/less-grid-system
i think its quite easy to use and doesn't need any classes in the markup.
Doesn't work in IE