Skip to main content

Using pure CSS the root font size scales up and down proportionately, between defined values, dependent upon the viewport width.

- (incept: )

Tool: Fluid-responsive font-size calculator

18th May 2020

A simple utility to easily calculate fluid-responsive property values (font-size) for embedding directly into your CSS.
Updated to include both clamp and min-max methods.

Easy-peasy, stretch & squeezy

This method is in full use on this site, and was in commercial use on components in Tesco's 2017 Food Love Stories

In this example the font size is set at 1rem (16px) up to 48rem (768px) viewport width. It then starts increasing to meet the upper defined value 2em (32px) at 120rem (1920px) wide.
All controlled from a single CSS statement.

Remember to define all font-sizes in em, rem or percent.

Language CSS
/* 1rem(16px) @ 48rem(768px) increasing to 2rem(32px) @ 120rem(1920px) */
/* Ems strongly recommended on media queries! */
@media (min-width: 48em) {
  :root {
    font-size: calc(1rem + ((1vw - 0.48rem) * 1.3889));
    /* Where: 1.3889 = 100 * font-size_difference / viewport_width_difference */

    /* Safari resize fix */
    min-height: 0vw;
  }
}

Where:

Language Mathmatics
fontSizeCalc = 1rem + (1vw - 48rem / 100)
fontSizeCalc = fontSizeCalc * 100 * fontSizeDifference / viewportWidthDifference

fontSizeDifference = maxFontSize - minFontSize
                   = 2em - 1em  (or 32px - 16px)
                   = 1em  (or 16px)

viewportWidthDifference = viewportMax - viewportMin
                        = 120em - 48em  (or 1920px - 768px)
                        = 72em  (or 1152px)

Using pixels:
fontSizeCalc = 100% + (1vw - 768px / 100) * 100 * 16px / 1152px
             = 100% + (1vw - 7.68px) * 1.389

Using em or rem:
fontSizeCalc = 100% + (1vw - 48rem / 100) * 100 * 1em / 72em
             = 100% + (1vw - .48rem) * 1.389

Alternatively, in longhand:
fontSizeCalc = min_font_size_in_rem + (max_font_size - min_font_size) * ((100vw - min_viewport_including_unit) / (max_viewport - min_viewport))

Font scaling doesn't stop at the top setting but continues to increment at the same rate.
This behaviour may be stopped, or adjusted further, by adding another media query:

Language CSS
/* Stop font scaling above 1920px */
@media (min-width: 120em) {
  :root {
    font-size: 2rem;
  }
}

CSS methods: clamp and min-max

Two more methods have bubbled to the surface of late. Clamp and min-max. Both of which remove the requirement to use media queries, and thereby simplifying the CSS. Here's the same example as above using these methods:

Clamp method - language CSS
/* 1rem(16px) @ 48rem(768px) increasing to 2rem(32px) @ 120rem(1920px) */
:root {
  font-size: clamp(1rem, calc(1rem + ((1vw - .48rem) * 1.389)), 2rem);
  min-height: 0vw;
}
Min-max method - language CSS
/* 1rem(16px) @ 48rem(768px) increasing to 2rem(32px) @ 120rem(1920px) */
:root {
  font-size: min(max(1rem, calc(1rem + ((1vw - 0.48rem) * 1.3889))), 2rem);
  min-height: 0vw;
}

The only downside to these methods is browser support. Currently (2020), for production, I still recommend using the media-query version, but that should change with time. See Can I Use: CSS Math functions.

For more details on these newer methods please see Chris Coyer's article Simplified Fluid Typography.

Applied to a Flexbox layout

The methods presented will scale any property sized using pixel, em or rem. Check out Fluid-responsive property calculator.

Also see the stand-alone demo or the CodePen demo.

Safari resize issue

Safari will not recalculate the font size upon page resize. This issue can be resolved by adding a min-height: 0vw to the class.