Responsive Font Size with CSS

Making your font-size respond to viewport or container size should be a must to complete your responsive designs. Having a fixed font-size accross devices is not always a good idea. The key point is to get a readable font size and a comfortable line length in most viewports. CSS viewport units and media queries provide the means to implement a responsive font size.

Font Size and Line Length

There are lots of different views on which is the best pixel font size, or which is the minimum readable size. What is certainly true is that large fonts are more accesible and comfortable to read. The trend during the last years has been toward increasing font-sizes. Most websites today use font sizes ranging between 14 and 18 pixels for body text. Usability experts recommend a font-size of at least 16px.

There's much more to font sizing than it appears. Paying attention to the number of words per line is also key. We have all experienced the stress of reading narrow columns of text with two words per line. But what about long lines? Long lines tend to be hard to focus because we use the start and end of the lines as references unconciously. However, a 2005 study showed that we tend to read faster text with long lines of up to 95 characters, which is equivalent to approximately 18 English words.

As a general rule, use the largest font-size that doesn't look disproportionate and results in lines with 20 words or less (all words count).

Getting the same physical font size and the same number of words per line in all devices would happen only in a world with a single universal screen size (imagine it!). There is obviously a compromise between them.

Line Height

A third measurement to take into account is line height or line spacing. Line height doesn't involve a compromise because it only affects the page height. That means there is no reason to get it wrong. Most sources recommend a line-height of 1.2 to 1.45em for good readability and aesthetics.

Summarizing, the general recommendations for font-size, line-height and line length are:

Recommended responsive font size, line height and line length

That being said, there are two main ways to implement a responsive font size: viewport units and media queries along with good old pixels and ems.

CSS Viewport Units

CSS viewport units: vw, vh, vmin and vmax were specially created to allow lengths in CSS, including font-size, to be relative to the viewport size. They allow gives a truly responsive font-size, with its size as a percentage of the viewport width or height.

  • vw stands for viewport width. 1vw equals 1% of the viewport width.
  • vh stands for viewport height. 1vh equals 1% of height.
  • vmin is relative to the shortest dimention (width or height), and vmax to the longest.

The Problem with Viewport Units

It all sounds too good to be true until you try setting a responsive font size in viewport units. There are two main problems:

  • Text gets too large or too small. Setting font-size: 1vw will pruduce 19px letters in 1920px wide displays (okay...), but 6px letters in 640px wide viewports! Ugh!
  • Viewport units don't account for max-width. The viewport size might be larger than the site's max-width and vw doesn't care. The text will get larger while the rest of the layout stays the same. The same occurs for min-width.

Do Viewport Units for Responsive Font Size Make Sense?

As I see it, pixel and em units favor getting right the physical letter size in expense of line length, while viewport units favor getting roughly the same words per line accross devices in expense of letter size. What I mean is, you'll get text readable on any device by simply setting font-size: 16px but you'll get lines too long in large desktop displays and too short in narrow viewports. Using viewport units for a responsive font size, you can achieve optimized line lengths but extremely small or large text depending on viewport. In the end, you'll absolutely need media queries if you are using vw units in font-size rules, but not necessarily with px sizes (though it's recommended).

There is a reason why this happens: most computer screens have similar pixel densities and modern mobile devices adjust by reporting viewports smaller than their real resolution to make up for their high pixel densities. For example, some 1920x1080px phones have a viewport size of just 640x360. What this means is that 16px text takes much more than 16 real pixels, 48px in fact (16*1920/640). vw units are not affected by devices reporting small viewports, 1% is 1% of the viewport in centimeters, real or fake pixels. The end result is that vw units don't take advantage of the viewport size adjustment made by mobile device browsers. 1% of your phone's width is extremely small compared to 1% of your computer screen.

You can't have everything. Again, as I see it, getting right the font size is much more important. Responsive font sizes are not that great for reasons that were obvious from the beggining.

Both vws and px/ems will require you to use media queries for an optimized sizing. If you know exactly what you are doing, vw units might make sense, but beware, you'll need quite a few breakpoints in your media queries. Text sizing plays by rules different than those of box sizing.

Pixels, ems, rems and Media Queries

The second way to implement a responsive font size is to use media queries along with fixed-size text, using ems, rems and px values:

  • px values specify the height of the letters in CSS pixels
  • em is relative to parent's font size, eg. 2em = 28px if parent element's font-size is 14px.
  • rem (root em) is relative to the html element's font-size. 1 rem measures the same through the whole document. ems get hard to maintain in rules nested too deeply, but rems have no problem.

The best way to use ems and pixels is to specify a pixel font-size for the html element and use ems and rems for the rest. There are several reasons to do it this way:

  • The CSS is easier to mantain. Increase the html elements font-size and all the text gets larger. Using pixels would require to change each rule.
  • Using media queries gets easier for the same reason. You don't have to change each rule, just the html element and fine tune what's necessary.
  • Some browsers (IE8 and below) do not allow resizing fonts set in pixels. Users won't be able to increase the font size in those browsers.

How to actually make the font size responsive? This is where media queries come in. If you are using ems, simply change the html font-size as necessary and fine tune the details. For example:

html {
    font-size: 20px;
}
.unbehaved-element {
    font-size: 2em;
}
@media(max-width: 1580px) {
  html {
    font-size: 18px;
  }
  .unbehaved-element {
    font-size: 1.9em; /* Fine tune unbehaved elements */
  }
}
@media(max-width: 980px) {
  html {
    font-size: 16px;
  }
}

Never go below 14px for body text and try to get lines long enough without overdoing it in large screens. Count the number of words per line (every word counts) and try to keep it below 20 in all viewports.

Leave a Reply

Allowed tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>