Responsive fonts using css clamp()

If you have wrote CSS for fonts before you have probably experienced having to introduce a lot of media queries for different breakpoints.

A designer will provide designs for mobile/desktop and then the developer ends up asking “what about tablet?”, sound familiar? The output of those decisions could end up like this:

:root {
--heading-font-size: 3em;
--heading-font-size-tablet: 6em;
--heading-font-size-desktop: 9em;
}
body {
font-size: 16px;
}
h1,
.h1 {
font-size: var(--heading-font-size);
}
@media screen and (min-width: 48em) {
h1,
.h2 {
font-size: var(--heading-font-size-tablet);
}
}
@media screen and (min-width: 64em) {
h1,
.h2 {
font-size: var(--heading-font-size-desktop);
}
}

With technology changing so fast and new devices being released everyday our websites have to try and cater for those new screen sizes. Media queries solve only half the problem by setting fixed breakpoints at certain screen sizes. What if we could just make our fonts scale with no media queries and it’s implemented in one line of css? This is where CSS clamp() comes into the mix.

CSS clamp()

CSS clamp is a function that sets responsive unit sizes without any media queries. The function takes 3 parameters in this order:

  • min — Where to start scaling from
  • viewport width —The range determines how fast the min scales to the max based on the screen getting larger
  • max —when to stop scaling
clamp(min, viewport-width-unit, max);

Applying clamp() to our font example

When using clamp with fonts I tend to make the range to be the maximum container width so when the browser is wider than that container, the font is at its maximum size. In the diagram below it shows how this works. In my example, my container is 80em (1280px) and my maximum font for my heading is 9em (144px).

When the browser width is greater than 80em the maximum font size will be 9em. When the browser width is less than 80em my font slowly starts to get smaller and smaller until it has reached 3em. Once 3em is reached, the browser stops shrinking the font size. This is how it looks in code:

:root {
--global-h1-size: clamp(
3em,
calc(9 / 80 * 100vw),
9em
);
}
h1,
.h1 {
font-size: var(--global-h1-size);
}

Browser support

On CanIUse CSS clamp is supported in around 86.8% of browsers so it looks quite promising to use now in production code.

A fallback suggestion could be to use css supports to put back in the media queries or set another font-size property before so when the browser does not recognise the clamp function it falls back to a default font-size. It depends on your target audience and how much conversion those browser bring to your website.

// IE11 is 9/10 a large screen so fallback to large size feels like a good solution
font-size: 9em;
font-size: clamp(3em, 11.5vw, 9em);

Conclusion

And thats it! Using clamp makes your house styles for fonts a lot easier to manage across multiple screen sizes. I feel like this approach caters for a wider audience of device users where as the media query approach is quite fixed.

When I discovered this I was in the middle of making some house styles for my website and I literally was baffled from how little code you have to write to make it work. This gif described the moment…

Shia Labeouf Reaction GIF

Heres a link to my CodePen which shows clamp in action.

https://codepen.io/code-mattclaffey/pen/dypoyzq

Resources

https://vw.joealden.com/ — really handy calculator tool that calculates the breakpoint width based on the font size.

Advocate for Site Speed, PWA’s and Accessibility and UI Libraries