Let’s take a look at what it takes to build a grid overlay with CSS. It will be responsive, easily customizable and make heavy use of CSS variables (known more accurately as “CSS custom properties”). If you aren’t familiar with custom properties, I’d highly recommend reading What is the difference between CSS variables and preprocessor variables? and watching Lea Verou’s enlighting talk on using them.
This grid overlay that we’re building will consider a developer tool, as in, a tool just for us, not really our users. So, let’s not worry too much about browser support (If you do care, check out caniuse… data on custom properties). While it’s impossible to preprocess custom properties to behave exactly the same as native support, if you use them just like you would preprocessor variables, tools like the postCSS plugin cssnext can transform them into CSS compliant with older browsers.
Preface
A couple of weeks ago, at work, I simplified the media queries on one of our projects and added a layout component based on the same principles as Flexbox Grid. Some of my fellow designers didn’t fully understand the responsiveness and fluidity of it, so I created a toggleable grid overlay to help them visualize it.
My hope is that this can be a tool to aid layout-related conversations on our teams and make sure we don’t use too many bespoke widths, paddings etc.
Terminology
Working as a front end designer I want all developers and designers to speak the same language (as much as possible) so I’ve chosen a terminology for the CSS variables that digital designers are also familiar with:
- Columns: The vertical divisions of the page.
- Gutter: The space between the columns.
- Offset: The space between the sides of the viewport.
- Baseline: The vertical rhythm used for text.
Making the Grid
1) “Box”
Let’s use a pseudo-element on the element to display the grid on top of all of our content. We want the overlay to work with a fluid layout, so we give the element a width off `100% – (2 * offset)` and also a max-width so the grid overlay doesn’t grow wider than our layout.
2) Columns
If you look at the grid you will notice that the repeating pattern is column+gutter pairs. We’re using repeating linear gradients as a background-image
. We’ll set the size of the background-image
to 100% + gutter making the repeating pattern 100% / columns wide and the actual column (100% / columns) – gutter wide.
As a side note, I also tried using regular linear gradients with background-repeat to get the lines more pixel perfect. It didn’t work because pixel rounding resulted in imperfect total width whenever the layout width wasn’t dividable by the number of columns.
3) Baseline
We also draw the baseline using repeating linear gradients but it’s slightly simpler since we don’t add horizontal gutters and we want it to be just a line instead of a block.
Let’s also add a baseline-shift variable that allows us to shift the baseline slightly upwards or downwards. We apply the baseline shift by simply adjusting the background-position
.
4) Media Queries
Now that we have our basic setup, let’s introduce some media queries. If you look back at the math that we’ve used so far, you can see that none of it is tied up to any specific number of columns, gutter width, etc.
We use a mobile first approach and only include variables in the media queries when we want to change them. To make it clear for everyone using the overlay that we’ve passed a new breakpoint we also change the color at every breakpoint.
I recommend opening the Pen in a new tab and see how it behaves when you change different variable values and when you resize the viewport.
If you made a mental note in step 1 saying “but what if I want specific layout widths at specific breakpoints?” then now is when you can easily introduce that logic by setting --max_width
for each media query.
5) Help Text
Designers like to think about mockups for different devices — which is generally a good thing as it’s critical that a website looks awesome on those different devices — but sometimes they forget that the layout on an iPad should work all the way up and/or down to the next breakpoint.
Breakpoints aren’t normally called “iPhone”, “Galaxy Note 🔥”, “iPad” etc. for many reasons including the above. A breakpoint denotes where a new range starts and it’s not device specific.
To make it more obvious what our breakpoints are called, we can add the names to our grid overlay.
I have a dream that one day a designer doesn’t come back to a developer and say: “we need to adjust how it looks on iPad” but instead says “we need to adjust how it looks on medium”.
Go Further
What about lines for the columns and gutters too? Easy, it’s just CSS. What about adding more breakpoints? Easy, it’s just CSS. What if I want different colors? Easy… you get it. 😄
You can see a more advanced example here:
I’d love to get your input either here or on the GitHub repository which also includes a Chrome extension using this approach.
Neat!
Cheers :)
This looks great, will definitely think about adding something like this to my toolkit. I’ve been struggling a bit lately with breakpoints and whether to keep them to s/m/l/xl etc. or just create them as needed (atomic). Curious what your take is on this, you mentioned simplifying your approach. Thanks!
We currently only have (base), S, M and L at work.
It seems to work fine but we also use flex box all over the place which gives us some stretching/shrinking etc. capabilities.
What I’m currently looking at is introduction aspect ratios for all of our cards — again in an effort to have fewer custom sizes.
Awesome idea! You may want to add
pointer-events: none;
to the elements as well, so that you can click links underneath.Cheers, added — forgot to add that for the demo :)
Very cool tool dude! I also have a dream that designers one day adhere to generic naming instead of popular device type.
Soo awesome!