Skip to content

Font sizes and units

Declaring a size for your fonts sounds like it should be fairly simple, but it’s a surpringly complicated topic, because we need to decide what unit to use.

To declare a font size, we need to use a CSS length units, which we have a lot of.

The most common CSS length units are:

  • px
  • %
  • rem
  • em

While pixels is fine for many use cases, it’s considered bad practice to use it for declaring a font size because it can override a users preference. Instead, we should use a relative unit.

Percentages could work, but most of the time, you’ll find that people use either em or rem.

The em unit is a bit strange, in that it is not the same as what an em is in the world of print typography. If we use em, the unit is sized relatie to the parent’s font size.

.parent {
font-size: 20px;
}
.child {
font-size: 0.75em;
/* computes to 20px * .75 = 15px */
}

While this doesn’t happen often, it could lead to issues with nested elements.

html {
font-size: 10px;
}
ul {
font-size: 1.25em;
}
li {
font-size: 1.25em;
}
span {
font-size: 1.5em;
}

What is the computed font size of the <span> in this HTML?

<ul>
<li>Em units can cause problems</li>
<li>when you aren’t careful</li>
<li>a normal list item <span>with a nested span</span></li>
</ul>

It would be 23.4375px

Here is a regular paragraph, with a nested span inside of it.

  • Em units can cause problems
  • when you aren’t careful
  • a normal list item with a nested span

This isn’t to say that you should never use the em unit. In reality, you won’t often declare font sizes like I did above, and many people use them regularly. I don’t use them too often for font sizes, except when I want something to scale like this on purpose.

Percentage and em are very similar.

<h1>Picking a font size is <span>suprisingly hard</span></h1>
h1 {
font-size: 60px;
}
h1 > span {
/* these are the same */
font-size: 0.5em;
font-size: 50%;
}

The rem unit is a root em, meaning it is based on the font size of the root of our document, which is the <html> element’s font size.

This means that it’s much more consistent, even if you have nested font sizes.

html {
font-size: 10px;
}
ul {
font-size: 1.25rem;
}
li {
font-size: 1.25rem;
}
span {
font-size: 1.5rem;
}

In this case, no matter where we use our span, it’ll always be 15px in size.

line-height is used to control the space between lines of text. In the world of typography, they call this leading (though it’s measured a little differently).

You can use a specific size for line-height, or a unitless number, which is more commonly used. When you use a unitless number, you multiply the font size by that number to get the computed line height.

h1 {
font-size: 3rem;
line-height: 3.5rem;
}
h2 {
font-size: 2rem;
line-height: 1.25;
/* 2 * 1.25 = 2.5rem */
}

General rule of thumb for what values to use

Section titled “General rule of thumb for what values to use”

font-size and line-height have a bit of an inverse relationship. The larger the font-size, the smaller your line-height should be, and vice versa.

The default line-height from the browser is 1.4, which is an awkward middle ground, being too tight on small text, and too loose on large text. I’d suggest declaring a line-height of 1.5 or 1.6 on the <body>, and then adjusting it for larger text. Except in extreme cases, the smallest you might go is 1 or 1.1.