Easy-peasy Rem Conversion with Sass

I love rem. I’ve been using it since I first read about it in Jonathan Snook’s article, and even more so since I started building responsive websites.

So what is rem?

Rem is a value that is relative to the root font-size, meaning the font-size that is set on the <html> element. The browser by default sets the font-size at the root to 16px.

There are some articles around about why rem is good and super handy, so I won’t go into too much detail here. But in short, rem is awesome because:

  • It works like pixels in that you don’t get compounding issue like you do with em and the computed value is always the same no matter where the value is set.
  • It is better accessibility wise as it can be scaled like em, so users can resize the text on the page.
  • In responsive design, you can set a different font-size on the <html> at each breakpoint and the text on your site will scale proportionally according to your root font-size.

The only “issue” with rem is that it’s not supported by older browsers, namely IE8 and lower. So to use it, you’ll need to include the font-size in px as a fallback. But in my eyes, its benefits outweigh this small “issue” by far.

Using rem in our projects

Since we started using Sass for our projects, to make things more convenient, we wrote a mixin that will convert the input px to rem. It also outputs the px value as fallback for browsers that don’t support rem.

Creating the function

So first step, we need to write a Sass function that gets the rem value based on the px value that has been passed in. To do this, we need to divide the input px value with the default 16px set by the browser:

@function calculateRem($size) {
  $remSize: $size / 16px;
  @return #{$remSize}rem;
}

You might ask, “What if the user has a different default font size in their browsers”? Well, the great thing about rem is that the text will just scale proportionally like em! Pretty good, right?

Creating the mixin

Next we create a mixin that calls the function:

@mixin fontSize($size) {
  font-size: $size; //Fallback in px
  font-size: calculateRem($size);
}

Now your mixin is ready to be used! To use it, simply include the mixin wherever you need to declare a font-size.

Sass:

h1 {
  @include fontSize(32px);
}

Output:

h1 {
  font-size: 32px;
  font-size: 2rem;
}

With simple Sass functions and mixins like this, we save a ton of time and human errors from punching numbers into our calculators.

You can find all the code to convert rems from pixels on the OOCSS open source project.


Posted

in

, , ,

by

Tags:

Comments

12 responses to “Easy-peasy Rem Conversion with Sass”

  1. Anahkiasen Avatar

    There’s actually a mixin for that baked-in Compass if you want.

    1. Nicole Sullivan Avatar

      @Anahkiasen – sweet! Can you provide a link for everyone?

  2. Chris Pearce Avatar
    Chris Pearce

    Opera Mobile doesn’t support ‘rem’, good to know for responsive sites.

    Also what’s your view on using ‘rem’ for line heights ? 🙂

  3. Hung-Su Avatar
    Hung-Su

    This is an essential part of any Sass dev’s arsenal =) Personally, I like the name ‘font-size’ for my mixin because I think camelCase in CSS is weird xP Is there any reason why you like the calculation of rem to px in a separate function?

  4. ulf gjerdingen Avatar
    ulf gjerdingen

    greatness 🙂

    i just wonder how to handle it when i set up variables with pixel values.
    something like this


    // variables
    $base-font: 100%;
    $header-size: 56px;
    content-h-padding: 3.125%;

    do i have to calculate the $header-size manually or could i implement the mixin here as well?

    <3

  5. ulf gjerdingen Avatar
    ulf gjerdingen

    oh. i think i got it…
    i can leave the variable in pixels and just:

    @include fontSize($header-size);

    *facepalm*

  6. Fiona Chan Avatar

    @Chris – I always use unitless line-height 🙂

    @Hung-Su – There’s no particular reason. I suppose you can separate out the function in its own file but so far we haven’t needed to use that function other than for font-size.

  7. Å ime Vidas Avatar

    I’m confused. If you set font-size: 10px on <html> (say, via media query), then fontSize(32px) will still result in 2rem, which is then computed to 20px, right? So, fontSize(32px) results in a computed value of 20px if the <html> font-size is set to 10px. Isn’t that a bit confusing?

  8. Fiona Chan Avatar

    @Å ime: That’s an interesting point. I’m not sure 100% right now how to make that more clear in the Sass file. It would be more clear if you can see the value you’re setting is in rem rather than px, but for now a lot of people still find it easier to think and set the value in px, especially when translating a design into build.

  9. Hannes Avatar
    Hannes

    You could just write

    @mixin fontSize($size) {
    font-size: $size; // Fallback in px.
    font-size: ($size / 16px) * 1rem;
    }

    I wonder how to write similar mixin for lineHeight so that it would know how big the current font-size is? Second parameter?

  10. Jamie Avatar
    Jamie

    @Hannes

    “I wonder how to write similar mixin for lineHeight so that it would know how big the current font-size is? Second parameter?”

    There’s no need for a separate mixin for this. If you set your line-height in either % or without a unit, it is proportional to the font-size. So the following (with a 16px font-size):

    line-height: 2;
    line-height:200%;

    would both give a 32px line-height.

    You can also use the font shorthand:

    font: 16px /2 georgia, serif;

    where “/2” is the line-height.

    (px used above for illustration only – use rems!)

  11. Alejandro Avatar
    Alejandro

    Hi, Does this technique works when scaling fonts in different viewport sizes?, like using media queries.