Using CSS Grid and Viewport Units to build responsive site previews

When we started work on the all-new properdesign.co.uk we wanted a way to show how our designs work across different screen sizes. A Google image search for responsive design yields approximately one squillion versions of the same design pattern – a phone, a tablet and either a laptop or desktop monitor all displaying the same site. A sizeable proportion of these (0.6 squillions) is made up of Photoshop templates to help you create a static image of the site in its various states. We weren’t too keen on a static image solution as it tends to perpetuate the above the fold myth and a lot of interesting things happen below that imaginary fold.

This problem was tackled with some style a couple of years ago by Headscape who opted for iframes in a resizable container – which is a really great approach

  1. You can transition between views of the site and see the CSS magic happen
  2. You get to see the real, live site with clicky, scrolly, selectable guts

ultimately, however, it wasn’t for us:

  1. The preview module itself is not completely responsive – Headscape opted to not show this module on smaller displays, our solution should be responsive
  2. You switch which layout is displayed – we’d like to be able to see them alongside each other
  3. You have to load the real, live site with clicky, scrolly, selectable guts.

Starting Grid

Because I am old and started designing for screens on graph paper, I loved the idea of creating a grid of squares to work with. A 20 column grid would give me enough resolution to play with, without having to think too much.

A sketched layout on dotted grid paper
A simple 20×10 grid

Intrinsic ratios can be a bit of a nightmare on the web, but not so much with viewport units. Our preview module would use the full-width of the site, so I created a 20 column grid with each column set at 5vw (5% of the viewport width). While the initial layout requires 10 rows, that number may vary based on media queries, so I set grid-auto-rows to 5vw.

.devices{
  display:grid;
  grid-template-columns:repeat(20, 5vw);
  grid-auto-rows:5vw;
}

Positioning each of the devices using the grid-column and grid-row shorthand properties couldn’t have been simpler. In both cases, you provide a start-point and an optional end-point or span. Like so

/* Start on column 2, row 3
3 columns wide and 6 rows long */

.mobile{
  grid-column:2 / span 3;
  grid-row: 3 / span 6;
}

/* Start on column 13, row 4
7 columns wide and 5 rows long */

.tablet{
  grid-column:13 / span 7;
  grid-row: 4 / span 5;
}

/* Starts on column 3, row 2
13 columns wide and 8 rows long */

.laptop{
  grid-column:3/span 13;
  grid-row: 2 / span 8;
}

Then I added a full height & width div to act as the screen withoverflow-y:scroll; so users can scroll the screenshot in each of the devices. You can see our first draft here.

See the Pen devices design pattern with css grid and viewport units by Marc Heatley (@TheHeat) on CodePen.

Not too bad, but we found the scrolling didn’t always take, that is to say, that in some cases to scroll inside one of the devices you may need to have clicked on the device to activate scrolling. Also, if you remember, we really wanted users to be able to compare these layouts across multiple devices at the same time and while this comes close, what if all of the screens scrolled together?

Obviously, that would take a little sprinkling of Javascript magic… let’s do that.

The basic idea here is that

  • when we mouseover (or touchstart for touchscreens) any of the devices we addEventListener to that device, firing our scrollAll() function
  • scrollAll() takes the scroll position of the activated device and converts it into a percentage and updates the scroll position of each of the other devices
  • if the pointer leaves the device, we unhook scrollAll() with removeEventListener

See the Pen devices design pattern with css grid and viewport units by Bones (@Bones5) on CodePen.