Recently, I needed to implement a design that scaled the space between components as the viewport changed size. The requirement is nothing new but I wanted to find a way to acheive it without having to re-declare multiple style rules in a media query. This article explains the technique I used.

The design in question starts out as a linear list of elements that are cloesely spaced to make best use of a small viewport. As the size of the viewport increases, the elements begin to flow into columns and grids until we reach the final "desktop" variant. At key points in the design, font sizes and the space between elements need to increase to make use of the extra space afforded by a larger viewport — nothing new so far.

The following example is a bare-bones responsive layout with fixed font sizes and element spacing. When viewed on a small viewport the page looks okay, but as the viewport gets larger, more whitespace and larger font sizes are needed.

Try the bare-bones demo

In this example, to increase the spacing between elements, most of us would write a media query or two to redeclare the relevant CSS properties with new values — while this works, it's not particularly efficient (re-declaring the same rules over and over never sits well with me). If you use utility classes to control things like element spacing then the problem is not as bad, but you'll probably still end up writing duplicate rules.

I wanted to experiment with ways of achieving this without having to write a lot of additional CSS. Here's what I came up with...

Enter, responsive rem units

The techinque uses rem units to set a baseline for property values. Style properties such as padding and margin can then be defined using rem units. A combination of media queries and font-size adjustments are used to scale these values at key points in the design without affecting the page font or any em based property values. Scaling of rem units is controlled using the following CSS:

/* Set our base font size (for mobile)
-------------------------------------- */
html {
  font: 80% / 1.5 Arial; /* the base font-size */
}

/* Set our medium viewport spacing
---------------------------------- */
@media (min-width: 35em) {
  html {
    font-size: 160%;  /* double the base font-size */
  }
  body {
    font-size: 50%;  /* half the font-size */
  }
}

Let's walk through that...

The font-size value of the html element is set to target small viewports — for the purposes of this demo, I've settled on a size of 80%. When the viewport reaches a minium width of 35em the font size of the <html> element is doubled, which doubles the size of a rem unit. Increasing the font size of the <html> element will scale fonts and other elements on the page. To correct this, the font size of the <body> element is also halved. Fonts now render at the same size, but rem units are now twice the size.

If we go back to the first demo and switch out any padding or margin em units for rems, it's now possible to control element spacing using just the font-size property. The next demo show this in practice. If you resize the viewport you'll see the space between various elements changes:

Try the responsive space demo

Scaling fonts

Now we're able to scale space, we can leverage the same technique to scale fonts as the viewport changes size. We do this by increasing the <body> font size:

/* Set our medium viewport spacing
---------------------------------- */
@media (min-width: 35em) {
  html {
    font-size: 160%;  /* double the base font-size */
  }
  body {
    font-size: 75%;  /* double the font-size */
  }
}

In this example we're doubling the size of the font when then viewport width reaches 35em. As demonstrated above, applying font-size of 50% the the <body> element would counter the doubling effect of applying 160% to the <html> element. By applying 75% we're only reducing the doubling effect by half, which doubles the <body> font size.

Try the responsive layout demo

Personal Achievements

  • 2015 JS1k – winner
  • 2014 Net Awards: Demo of the year – winner
  • 2014 Net Awards: Developer of the year – longlist
  • 2013 Public speaking for the first time
  • 2011 .net Magazine innovation of the year – shortlist

Referenced in…

Smashing CSS, CSS3 for web designers, Programming 3D Applications with HTML5 and WebGL and more.

I am very proud to have had my work referenced in a number of publications, written by some very talented people.