First a little background.

EMs

ems are scalable units that multiply the current font size. So if the current font size is 16px, and you apply a 2em rule to it, the resulting size is 32px.

This is great because you can scale elements with whatever font size is active in the browser rather than locking a font in at a specific pixel size. But the down-side is that you can sometimes end up with unexpected results when ems are applied within elements that have other ems applied.

Say you have the element at 16px, and then apply `1.5rem` to a `<div>`, which results in a font size of 16px + 8px = 24px. So far so good. But then you have another class, maybe a header, that has a `2em` applied to it. By itself sitting on the, that class will have a font size of 16px x 2 = 32px. But if that class happens within the already-emd <div>, it now has a font size of 24px (the current font size of the <div>) times 2 = 48px. What’s more that same class applied to a different element that has .5em (or font-size 16px x .5 = 8px), will end up with a font size of just 8px x 2 = 16px.

By now your 2em header class ends up on the page appearing with 3 different sizes:

  • 32px when it’s alone on the page,
  • 48px when it’s inside the 1.5em <div>, and
  • 16px when it’s inside the 0.5em element.

As ems multiply, keeping track of all the possible variations becomes next to impossible.

REMs

Enter rems. Rems are Root ems. Meaning that like ems, they scale a font size. But unlike ems, they all scale from the font size of the document root element (which in HTML is, you guessed it, the `` element).

With rems, you set the font size of the element at 16px (or 100%, since the default font-size of in modern browsers is 16px) and no matter where you are on the page, something tagged with 2.5 rem is going to render with a font size of 16px x 2.5 = 40px.

Hooray!

But what about the older browsers that still don’t know what rems are? You can’t have them just ignoring all your font-sizes and rendering everything out at 16px.

Disaster!

For those browsers, you have to have a fallback in px for every rem you set, so you end up with a stylesheet that has a lot of rules like:

p {
    font-size: 16px;
    font-size: 1rem;
}

Wouldn’t it be nice not to have to calculate all those things and type all those extra lines?

Sass to the Rescue

Happily, there is, if you’re using Sass (or any other CSS pre-compiler – but this is about Sass).

There are 2 ways of going about it. The more typical arrangement I find around the web is setting the size of `` at 62.5% (which brings the 16px browser default size down to 10px).

Then, you can have Sass calculate everything by giving it a size in rems where the rem size is a tenth of the pixel size you’re looking for:

@mixin fontSize( $size: 1.6 ) {
    font-size: ($size * 10) + px;
    font-size: $size + rem;
}

Then anywhere in your stylesheet you can have your cake and eat it too by simply inserting the mixin:

p {
    @include fontSize(2.4);
}

compiles to:

p {
    font-size: 24px;
    font-size: 2.4rem;
}

One Step Further

But what if you’d rather not adjust the root font size? I happen to like keeping the root font size at 16px (100%), and then scaling it down for mobile. But calculating rem on a base 16 is math that I’d rather not do.

In that case, let’s have Sass do the math for us!

Here’s an alternate mixin:

@mixin fontSize( $size: 16 ) {
    font-size: $size + px;
    font-size: ($size / 16) + rem;
}

Again, drop this anywhere in your stylesheets, but now use the font size you’re aiming for in px for the size parameter:

p {
    @include fontSize(24);
}

which compiles to:

p {
    font-size: 24px;
    font-size: 1.5rem;
}

And there you have it: 1 mixin to rule them all.

You could take this even further by putting the rem calculation into its own function, which you can then drop into any other mixin (say for margins or padding) where you want to use rem with a px fallback.

But that’s a story for another day!