Phone 937.401.0915
Email Us

Scss Rem Mixin Now With a Better Fallback

Introduction To Rems

Rems are relative "ems", which means they take their value from the root of the document, not their parent. This makes font-sizing with rems much simpler than using ems. Chris Coyier sums up the difficulty of working with ems by saying,

One of the problems with using “em” as font sizes is that they cascade, so you are forever writing rules that select nested elements to reset them back to 1em.

Rems are the future for units of measure on the responsive web. Both Chris Coyier and Jonathan Snook have written about the benefits of using rems over pixels or even ems.

The Pixel Problem

At Sparkbox, we started using a rem Scss mixin to manage the setting of font-size in rems and to set a fallback font-size for older browsers.

1 2 3 4
@mixin font-size( $decimal-size ) {
font-size: $decimal-size * $base-font-multiplier * 16px;
font-size: $decimal-size * 1rem;
}
view raw font-size.scss hosted with ❤ by GitHub

This approach was a great first step, but it fell a bit short because of older versions of IE. The drawback to using rems with a pixel fallback is that pixels are not scalable in IE 8 or lower. If a user decides to increase the text size in those browsers, pixel-sized fonts will not scale. IE 8 and 7 both support full-page zoom, which somewhat alleviates the problem; however, there are cases where full-page zoom isn’t optimal. IE 6 doesn’t even support full-page zoom, so users on IE 6 are stuck with pixel sized fonts.

Here is a quick note on how this mixin works. It's relatively straightforward; the only thing that might look strange is the $base-font-multiplier variable. This is akin to setting a percentage font-size on the <body> tag of a page, but, instead of worrying about that, we can set it once as a variable and then have our mixin handle it for us. Simply set the $base-font-multiplier variable to 1 if you want the equivalent of 100%, or set it to .65 if you want the equivalent of 65% on the body. There are other ways to handle this, such as Chris Coyier's mixin.

The Solution

After looking at the rem mixin, we settled on using font-size keywords as a way to set a scalable fallback for older browsers. According to the Mozilla Developer Documentation:

Keywords are a good way to set the size of fonts on the web. By setting a keyword font size on the body element, you can set relative font-sizing everywhere else on the page, giving you the ability to easily scale the font up or down on the entire page accordingly.

Font-size keywords give us seven keywords (or sizes) to use that will scale in older browsers. Seven keywords aren't very many, but if we limit their application to only the proper content areas, they can get the job done. The seven keywords, as defined by the spec, are:

  • xx-small
  • x-small
  • small
  • medium
  • large
  • x-large
  • xx-large

The purpose of using these keywords as fallbacks isn’t to make every text element on a page scalable, but to ensure that important content areas, like paragraph and article elements, are scalable and accessible in IE 8 and lower. Other content, like headings or hero text don’t necessarily need this flexibility. Now, let's adjust the previously mentioned Scss mixin to accomodate keywords:

1 2 3 4 5
@mixin font-size( $decimal-size, $keyword: null ) {
@if $keyword{ font-size: $keyword; }
@else { font-size: $decimal-size * $base-font-multiplier * 16px;}
font-size: $decimal-size * 1rem;
}
view raw _mixins.scss hosted with ❤ by GitHub

How To and Demo

To use our updated mixin, simply pass in a font-size keyword as an optional argument. If no keyword argument is passed to the mixin, the normal px-based value is assigned as the fallback.

1 2 3
html {
@include font-size(1, large);
}
view raw _smallest.scss hosted with ❤ by GitHub

To view a demo of our mixin in action, head on over to Codepen. If you are using Chrome, Safari, or Firefox, go ahead and inspect the various elements in the results pane to see the rem font-size overwriting the keyword or pixel values.

Enjoy!