DEV Community

JD Brewer-Hofmann
JD Brewer-Hofmann

Posted on

Responsive Font-Sizing, part 2

In part one, the primary method we used to achieve responsive sizing was media queries. In part two we will look to viewport units instead.

Viewport units

Viewport units are relative to the size of the browsers viewport, therefore they are incredibly responsive.

VH

The viewport height unit ( vh ) is equal to 1% of the viewport's height. So what does it look like when we use vh for our font-size?

h1 {
  font-size: 5vh;
}
h2 {
  font-size: 4vh;
}
p {
  font-size: 2.5vh;
}
button {
  font-size: 3vh;
}
Enter fullscreen mode Exit fullscreen mode

ex-vh

That is quite responsive, and no media query is necessary.

VW

It makes sense then that the viewport width unit ( vw ) is equal to 1% of the viewport's width.

h1 {
  font-size: 8vw;
}
h2 {
  font-size: 6vw;
}
p {
  font-size: 4vw;
}
button {
  font-size: 5vw;
}
Enter fullscreen mode Exit fullscreen mode

ex-vw

Once again, a very responsive unit, let's try flipping between portrait and landscape modes.

ex-vw-flip

That works pretty well, and there's two other viewport units to examine still.

Viewport Minimum

This unit is based on the smaller dimension of the viewport. If the viewport height is smaller than the width, the value of 1vmin will be equal to 1% of the viewport height. Similarly, if the viewport width is smaller than the height, the value of 1vmin will be equal to 1% of the viewport width.

h1 {
    font-size: 8vmin;
}
h2 {
    font-size: 6vmin;
}
p {
    font-size: 4vmin;
}
button {
    font-size: 5vmin;
}
Enter fullscreen mode Exit fullscreen mode

ex-vmin

That might be even better than vh or vw, because if a user flips their phone from portrait to landscape the font-sizes will remain the same.

Viewport Maximum

You would probably guess that viewport maximum (vmax) is based on the larger dimension of the viewport.

h1 {
    font-size: 4vmax;
  }
  h2 {
    font-size: 3vmax;
  }
  p {
    font-size: 2.25vmax;
  }
  button {
    font-size: 2.5vmax;
  }
Enter fullscreen mode Exit fullscreen mode

ex-vmax

Vmax functions very similarly to vmin. Between the two, I find it much more sensible to base my responsive sizing off of the smaller dimension of the screen using vmin.

Fluid Text with calc()

Here's where things get really interesting. I stumbled upon a formula that expands upon viewport units and adds in minimum and maximum values for font-sizes. The formula looks like this

min = minimum font-size integer
minPx = minimum font-size 
max = maximum font-size integer
screenMin = minimum screen size integer
screenMinPx = minimum screen size 
screenMax = maximum screen size integer

font-size: calc(minPx + (max - min) * ((100vw - screenMinPx) / (screenMax - screenMin)));

font-size: calc(24px + (32 - 24) * ((100vw - 320px) / (1200 - 320)));
Enter fullscreen mode Exit fullscreen mode

There's a lot to unpack here, if you want to understand it better checkout this awesome smashing magazine article. Let's take a look at this in action.

h1 {
    font-size: calc(24px + (32 - 24) * ((100vw - 320px) / (1200 - 320)));
}
h2 {
    font-size: calc(20px + (26 - 20) * ((100vw - 320px) / (1200 - 320)));
}
p {
    font-size: calc(12px + (16 - 12) * ((100vw - 320px) / (1200 - 320)));
}
button {
    font-size: calc(14px + (18 - 14) * ((100vw - 320px) / (1200 - 320)));
}
Enter fullscreen mode Exit fullscreen mode

ex-fluid

That sure is a handful to write, but it gives us an incredibly responsive sizing with guardrails to ensure our text never gets too large or too small. Coupled this technique with viewport sizing for your containers, and you can make some incredible responsive apps with no media queries.

Adding SASS or CSS precompilers

Abstracting away having to write this ridiculous calc function for every font-size in your app is the only thing left to do. Using SASS to write a reusable function can end up saving a lot of time. The only tricky part is remembering to add your minimum font size argument with a unit value to it, as well as without.

@mixin fluidText($minPx, $max, $min){
    font-size: calc(#{$minPx} + (#{$max} - #{$min}) * ((100vw - 320px) / (1200 - 320)));
}

h1 {
    @include fluidText(24px, 32, 24);

}
Enter fullscreen mode Exit fullscreen mode

I attempted to simplify this, with no success, I had to include two different variables for the same number. While that little bit was annoying, the end result is a life saver for me, and I'll be copying that mixin into many projects from now on.

I hope this helps anyone who is curious about making a more responsive app, and of course there's a lot more information out there.

Additional Resources

https://www.madebymike.com.au/writing/fluid-type-calc-examples/

https://www.smashingmagazine.com/2016/05/fluid-typography/

https://developer.mozilla.org/en-US/docs/Web/CSS/text-size-adjust

https://webdesign.tutsplus.com/articles/7-css-units-you-might-not-know-about--cms-22573

Discussion (0)