The REM Fallback with Sass or LESS

by CSS Tools

Hey there…

This post is 715 days old. It was written on 02.01.2013. Please make sure to be careful with the information provided and check a more recent source on this topic.

Since a while now word has spread to use the CSS unit rem for font-sizes and values in CSS. Here I want to explain how you can use a fallback in Sass or LESS to get rem working in all browsers.

View Gist with mixins

Why rem?

Let’s look into what rem means. We know of the em unit which is relative to the font-size of the parent element it is defined on. This means if one of the parents in the DOM-tree changes its font-size, the font-size of the child element changes too. In contrast the rem unit is relative to the root element of the page (this means the html element). Thus it is possible to define a font-size once on the root and make all other sizes depending on this size. Please switch over to Snook’s blogpost explaining what rem is to get more information about it.

If you ask yourself why you should use em instead of px, Chris Coyier wrote an article on why he switched to em instead of pixels a while ago for nearly all properties using units in CSS. Read this to understand why em and thus rem is so important.

I would encourage you to use rem (or at least em) for properties like padding, margin and sometimes even width instead of pixels. It makes your design even more responsive.

The drawback of rem is that it is not supported in all browsers that are used, even though the support looks pretty good: Internet Explorer is capable of dealing with rem since version 9. The versions before need a fallback. It is supported on the major mobile browsers except Opera Mini. Let us have a look on how we can define such a fallback using Sass or LESS.

A Sass Mixin

In order to get the pixel-based auto-calculation working as a fallback we need to define the font-size as a variable in Sass or LESS.
The following examples are in Sass with the SCSS-syntax.

$main-font-size: 16px;

We can now use this default font size on the root element:

html {
  font-size: $main-font-size;

Now we define a mixin that provides a fallback pixel-based size of the property based on the variable we defined before and in rem for capable browsers.

@mixin x-rem ($property, $value) {
  #{$property}: $value * $main-font-size;
  #{$property}: #{$value}rem;
}

What the mixin does is, that it takes the $property and calculates the value in pixels. This simple mathematic function is part of Sass. The $value argument is a decimal digit.

I like to prefix my own mixins with x- to easily distinguish them from other mixins. This is a part of the Idiomatic CSS principles by Nicolas too. I think previously I prefixed them with a namespace (mostly it was the- as a prefix, so you get the-transition) – but since there is a better convention with Idiomatic CSS I switched to it.

This mixin can be called like in the following examples:

@include x-rem(font-size, 1.4);
@include x-rem(padding-left, 2);

The output that is being produced looks like this for the first example:

font-size: 22.4px;
font-size: 1.4rem;

You can use Sass’ round() function to get an integer output for the px-based output. But every browser is capable to round 22.4px by itself to 22px since it is not possible to display 0.4px after all. (LESS has the same function.)

A Few Words On The LESS Mixin

In LESS interpolation for properties is current not possible with version 1.3.x. The maintainers aim to include it in version 1.4. For the time being we need to define a workaround for properties which is basically a JavaScript function which returns a sting that consists of two properties instead of one, while the first one is - which is basically no property an thus disregarded by the browser. The second is the property that we want to use.

Here is the first line of the mixin:

-: ~`(function () { return ';@{property}: @{px-fallback}'; }())`;

This only works if the LESS compiler uses the actual JS library. It does not work with lessphp or other compilers that are not JavaScript based.

Final Words

And that is it. The mixin provides a decent fallback for rem-based sizes of all kind. Since CSS runs stable with this version of a fallback and overwrites the pixel-based value because of CSS’ cascade we can use it without any problems. It works in old Internet Explorers.

Life is easy with rem. So look at the Gist and use the rem-fallback-mixins.

Sass and LESS mixins

Credit

I want to mention that I first saw this technique used by Divya Manian a year ago (beginning of 2012) when working on the HTML5 Please API project. I am not sure who developed this technique or where it comes from. Please let me know if you have a link.

Addition: The Susy framework has a Sass mixin which lets you easily convert units including the rem unit and a fallback as described here. (Head-tip Fabian Beiner.)

Addition 2: Steffen wrote a Sass mixin which lets you use the short notation of properties like margin or padding. Even mixing values as px and rem is working. Cheers!


Steffen

I really like the idea of this mixin, but I have one problem with it:

How would you do sth. like:

margin: 0 1.4rem 1.4rem 0;

with a mixin? I love using CSS-shorthand-notation, and I cannot get my head wrapped around a simple solution for this. Any ideas on this? I know this is an edge-case and writing

margin: 0; @include x-rem(margin-right, 1.4); @include x-rem(margin-left, 1.4);

would work, but I am lazy :-)


Neil Scott

Using WinLESS to convert my LESS stylesheets, my rendered CSS is full of remnants of the code: ‘-:;’

“-:;margin-bottom:15px;-:;margin-bottom:1.5rem; “

I tried removing these elements from the code, but that broke the LESS file.

Do you have any ideas? Thanks!


Brandon Brown

I use a (longer but) much cleaner approach I’ve found in my LESS.

https://gist.github.com/brandonb927/5665503



Dennis Gaebel

I’ve been a huge proponent of the REM since they’ve been whispered throughout the community. I use it heavily on Typeplate, but I’m also intrigued by the use of it in a media query condition (i.e. the parenthesis)

So for example:

@media screen and (max-width: 30rem) {…}

as opposed to…

@media screen and (max-width: 30em) {…}

The neat thing is that using rems inside a media query conditional allows authors to base a breakpoint on the default rem value (the html element) and will also change depending on your default rem size (say for instance you changed the html element’s font-size from 16px to 18px).

The tough thing with ems is that if you change the body font size to 18px your media query conditional based on your body element’s em default value (usually 16px) will always be based on 16px, but say you changed your html element to 18px -giving you an equivalent of 1rem- then your media query math for breakpoints can use 18px as the calculation value not 16px as it always is the case from setting the font size on the body element.

For a few months this approach to rems inside media query conditionals was broken in Chrome and Firefox but has since been resolved through the bug reports I have filed with each vendor, but alas nobody seems to have closed these reports as of yet and of course they are marked as resolved :\


Leave a Comment

Remember what your mother told you: Be friendly. Your email address will not be published.
Markdown-Goodies available.