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.
@mixin font-size( $decimal-size ) {
font-size: $decimal-size * $base-font-multiplier * 16px;
font-size: $decimal-size * 1rem;
}
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-multiplie
r variable. This is akin to setting a percentage font-size on the 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:
@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;
}
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.
html {
@include font-size(1, large);
}
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!