Flexible type with :root

One element of responsive web design that can be tricky to solve for is typography. Ideally you want to have type that’s as fluid as possible across different viewports. A conventional way of doing this might be to start with a base font size and then change it when you hit a specific breakpoint:

p {
  font-size: 1em;
}
@media screen and (max-width: 45em) {
  p {
    font-size: 1.25em;
  }
}

Here the font size doesn’t change until the breakpoint is reached.

Using :root

My preferred approach for more flexible type is to calculate the font size based on the viewport height and width using the :root selector:

:root {
  font-size: calc(1vw + 1vh + .5vmin);
}

Now you can utilize the root em unit based on the value calculated by :root:

body {
  font: 1rem/1.6 sans-serif;
}

Viewport units

You’ll notice the calc() function has been passed values in viewport units. Let’s quickly review those to understand how the root font size is being calculated.

  • 1vw = 1% of viewport width
  • 1vh = 1% of viewport height
  • 1vmin = 1vw or 1vh, whichever is smaller
  • 1vmax = 1vw or 1vh, whichever is larger

If we apply this to the viewport dimensions of the iPhone 7, which is 375x667, the calculated value of :root would be:

:root {
  font-size: calc(3.75px + 6.67px + 1.875px); /* 1vw + 1vh + .5min */
}

See the Pen Use :root for Flexible Type by Matt Smith (@AllThingsSmitty) on CodePen.

There will always be different approaches to responsive typography, and we should measure each by what we’re trying to solve for, beyond just a responsive state. I’ve found using :root this way provides the most flexible solution.