CSS Grid Layout with Responsive Breakpoints

8 Sep 2020
To leave a comment, type jam

Here's an easy way to build responsive layouts with a new-ish CSS feature (circa ~2017). It combines two techniques—CSS Grid + SCSS breakpoint mixins—in a way I hadn't seen in other tutorials/StackOverflow threads.

This is an alternative approach to older layout methods that depend on floats, flexbox, and tables. Mastering display: grid and taming @media queries can help free you from frameworks like Bootstrap, Tailwind, etc. You can write lightweight, maintainable CSS from scratch instead!

Here's what we'll make:

A simple layout that changes at a single breakpoint. It's easy to add more breakpoints and related CSS rules.

Table of Contents - CSS Grid Layout with Responsive Breakpoints

  1. Toolset
  2. HTML
  3. Responsive Breakpoints
  4. Grid Layout

A. Toolset ↑ Table of Contents

We'll combine CSS Grid Layout —supported by all major browsers beginning in 2017—with SCSS mixins to create a responsive layout.

Our goal here is a barebones starting point with as little code as possible. Basically, this is a scaffold for tinkering with CSS Grid in a useful context 1.

The following examples are written in Slim and SCSS. I explain most of the code with inline comments. These code samples are from a skeletal Rails app (repo here) but you don't need to understand Rails to follow along. File paths are relative to the app's root directory.

B. HTML ↑ Table of Contents

Here's the HTML (Slim) 2:

app/views/layouts/application.html.slim

Our stylesheet_link_tag (👆 line 8) imports two SCSS files:

app/assets/stylesheets/application.scss

The line order is important. We import breakpoints.scss first so we can call its mixins.

C. Responsive Breakpoints ↑ Table of Contents

breakpoints.scss does two things:

  1. Defines breakpoints, and
  2. Defines 3 SCSS mixins for interacting with the breakpoints elsewhere in our CSS:

Here is a heavily-commented version of breakpoints.scss (uncommented version here):

app/assets/stylesheets/breakpoints.scss

D. Grid Layout ↑ Table of Contents

Now we'll use CSS Grid to create a simple nested grid layout. I'll explain what we're doing before jumping into the code.

First we set up a grid on .page-grid. This grid has three (3) rows and one (1) column. The .sidebar and .main divs default to display: block and are therefore stacked. In other words, we're developing "mobile first."

Then, when window width exceeds 640px, our mixin applies a subgrid to #content. The .sidebar and .main divs sit side-by-side in the subgrid row at least 600px high. .sidebar has a grey background.

To be clear, display: grid is not really necessary for .page-grid in our example. I went with display: grid to make it easier to extend the layout later 3.

Below is a heavily-commented version of index.scss (uncommented version here):

app/assets/stylesheets/index.scss

Extending this grid from here is easy. Use respond-below(screen) and respond-above(screen) to apply breakpoint-specific CSS rules. You could also define additional breakpoints in breakpoints.scss and call respond-between($lower, $upper) to apply rules to ranges.

I hope you find this template and walk-through useful. Happy layout designing!

1 If you're looking for deeper coverage, I strongly recommend Rachel Andrew's Get Ready for CSS Grid Layout, which details all of CSS Grid Layout's features and specifications.
2 In a conventional Rails app, this code would normally span two separate files: app/views/layouts/application.html.slim and app/views/pages/index.html.slim. I've consolidated into one file for simplicity.
3 I've been debating when it's best to default to display: grid for layout elements in a design.