Grow your CSS skills. Land your dream job.

Last updated on:

Mixins for Rem Font Sizing

The rem font-size unit is similar to em, only instead of cascading it's always relative to the root (html) element (more information). This has pretty good modern browser support, it's just IE 8 and down we need to provide px fallbacks for.

Instead of repeating ourselves everywhere, we can use a LESS or SASS mixins to keep it clean. These mixins assumes:

html {
  font-size: 62.5%; /* Sets up the Base 10 stuff */
}
.font-size(@sizeValue) {
  @remValue: @sizeValue;
  @pxValue: (@sizeValue * 10);
  font-size: ~"@{pxValue}px"; 
  font-size: ~"@{remValue}rem";
}
@mixin font-size($sizeValue: 1.6) {
  font-size: ($sizeValue * 10) + px;
  font-size: $sizeValue + rem;
}

Usage

p {
  .font-size(13);
}
p {
  @include font-size(13);
}

(Thanks Gabe Luethje)


Another SCSS one with a different approach by Karl Merkli:

@function strip-unit($num) {
  @return $num / ($num * 0 + 1);
}

@mixin rem-fallback($property, $values...) {
  $max: length($values);
  $pxValues: '';
  $remValues: '';

  @for $i from 1 through $max {
    $value: strip-unit(nth($values, $i));
    $pxValues: #{$pxValues + $value*16}px;

    @if $i < $max {
      $pxValues: #{$pxValues + " "};
    }
  } 

  @for $i from 1 through $max {
    $value: strip-unit(nth($values, $i));
    $remValues: #{$remValues + $value}rem;

    @if $i < $max {
      $remValues: #{$remValues + " "};
    }
  } 
  
  #{$property}: $pxValues; 
  #{$property}: $remValues; 
}

So you can do:

@include rem-fallback(margin, 10, 20, 30, 40);

and get:

body {
  margin: 160px 320px 480px 640px;
  margin: 10rem 20rem 30rem 40rem; 
}

Comments

  1. Permalink to comment#

    I fond less escaping ugly so in cases like this I use font-size: @pxValue*1px;

  2. and if you really, really lazy (like me) throw in a little love for the line-height & add a basic 1.5 multiplier

    
    @mixin fontsize($size:1.6, $line: $size * 1.5){
        font-size:   ($size * 10) + px;
        line-height: ($line * 10) + px;
        font-size:   $size + rem;
      line-height: $line + rem;
    }
    

    SASS is just öwesome
    a quick node remember to put in the value as its an em not px ;)

    .foo{ @include fontsize:(1.5, 2);

  3. Ha! I knew it was only a matter of time before we would start seeing preprocessor code here.

    Thanks Chris and Gabe.

    For more robust sizing, These are the mixins I use:

    Rem by bitmanic and, in extreme cases, I use Scale, by mrdanadams.

    Keep ‘em coming.

  4. Permalink to comment#

    Don’t forget Stylus!

    Mixin:

    
    font-size($sizeValue = 1.6)
      font-size ($sizeValue * 10) px
      font-size $sizeValue rem
    

    Usage:

    
    p
        font-size(13)
    
    • Permalink to comment#

      *correction
      Tab spacing issue.

      
      p
        font-size(13)
      
    • *a more transparent method below

      font-size(_size)
          if unit(_size) == 'rem'
              font-size (_size*10)px
          font-size _size
      

      usage

      p
          font-size 1.2rem
      

      yields

          p{
              font-size: 12px;
              font-size: 1.2rem;
          }
      
  5. Thank you for this!

    Strangely it was outputting higher values (240px / 24rem instead of 24px / 2.4rem) so I modified it slightly for my uses:

    
    @mixin font-size($sizeValue: 1.6, $line: $sizeValue * 1.5){
      font-size: ($sizeValue * 1) + px;
      line-height: ($line * 1) + px;
      font-size: ($sizeValue / 10) + rem;
      line-height: ($line / 10) + rem;
    }
    
    • Surprised no-one commented when you fixed the math.

      I’ve been using rems haphazardly, but now trying to implement them properly before my next update.

    • Ando
      Permalink to comment#

      Is the value in the top example wrong?

      If $sizeValue: 1.6, then the value should be font-size(1.3) not font-size(13). That would explain Jonah’s issue.

      SASS noob so apologies if I’m completely wrong.

    • Line-height would be best applied unit-less, no?

  6. Permalink to comment#

    Shouldn’t the mixing be more like this:

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

  7. Hi.

    I aded the mixin as yo wrote but in the ouputet code, there only appears:

    
    h1 {
    font-size: 3rem;
    }
    

    Shouldn’t it be

    
    h1 {
    font-size:3rem;
    font-size:30px;
    }
    

    ?
    My Mixin:

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

    And the included snippet.

    
    h1 {
    		@include font-size(3);
    	}
    

    Where is the error?

  8. I’ve just created a collection of {less} mixins to help you converting pixels values to rem. The collection include support for font, margin, padding and position properties. I created them because it seems there’s nothing similar to support coders like me, that make heavy use of rem units Find out more at: https://github.com/christopher-ramirez/remixings

  9. Ryan
    Permalink to comment#

    For those using Sass, I wrote a mixin to handle rem conversions a while back (originally forked from @bitmanic’s). I stumbled on this post looking for something unrelated, but thought others might find it useful.

    • Permalink to comment#

      Nice mixin Ryan. Just gave it a whirl for the first time and it works very nicely. I particularly like the fact that it accepts both rems and pixels as arguments. Many thanks.

      Any word on when this may be rolled into Compass?

  10. Nour Akalay
    Permalink to comment#

    Hello,
    I was wondering if it wouldn’t be better to invert your solution to

    
     @remValue: (@sizeValue / 10);
      @pxValue: @sizeValue;
    

    I just assume that most of us think and work on our designs in pixels (especially with Photoshop) so it might be more intuitive to provide the pixel value and then calculate the rem rather than the other way around.

    It’s a matter of preference of course. Maybe if (when) I get as advanced as you I’ll start thinking in rems? :) (binary anyone?)

  11. Permalink to comment#

    Hi,

    Just wondering if anyone has converted this code to work with stylus, I have taken and tried to convert but not having any luck.

    Thanks

  12. Hey everyone!

    What about a mixin with body font-size at 100%?
    Would you just divide by 16 instead?

    Sorry but not a hawk at math

  13. Permalink to comment#

    Hey guys,

    Are there any thoughts about using em as a fallback instead of px, and then using two separate mixins? A lot of my site work now only uses ems, and px in rare cases, so I’m thinking about a mixin like this:


    .font-size(@sizeValue, @baseFontSize: 16){
    @remValue: @sizeValue;
    @pxValue: (@sizeValue * 10);
    @emValue:((@pxValue / @baseFontSize));
    font-size: ~"@{emValue}em";
    font-size: ~"@{remValue}rem";
    }

  14. @Sean The only advantage of rem over em is that it is more predictable, being relative to the font-size of rather than the font-size of the current element. If you’re going to go ahead and deal with ems, just use ems alone. The whole reason for fallbacks for rem is that rem isn’t well-supported by older browsers. ATM, it’s a case of ‘choose one': use rems for predictability and maintainability of code, but have to provide fallbacks in px, or just go with ems and mind your font sizes.

  15. Gah, stripped tags. That should read: “em is that it is more predictable, being relative to the font-size of html rather than the font-size of the current element.”

  16. Peter Marty
    Permalink to comment#

    I am a noob to Sass and have not implemented much beyond the basic functionality of mixins and variables. This is an awesome/efficient use of writing my rem fallback for font size, but, does anyone have suggestions as to how I might create something a bit more universal? i.e. I want to use rem (with a base sizing as shown above/as in http://snook.ca/archives/html_and_css/font-size-with-rem) and not have to write a fallback for things such as line height, padding, margin, text-indent etc.?

  17. @Peter Marty I’ve written a Sass mixin for that kind of general use: https://github.com/ry5n/rem.

  18. I have a solution for outputting rems with a px fallback on any property:

    https://gist.github.com/4153104/a5f13471af86e9835f18beda817ed772fcd9973a

  19. Evert
    Permalink to comment#

    One of the advantages or rems is that you can rescale the whole style by changing the base-size on html. However, when using this mix-in this would break the px-values.

    • Evert
      Permalink to comment#

      After some thinking I came up with this piece of code which allows you to add font-sizes relative to the base font-size and lets you change that base whenever needed (either with a redesign or when using different fontsizes for different media-types)

      @basefont: 16;
      
      html {
         font-size : ((@basefont * 100) / 16) + 0%;
         }
      
      .font-size (@size) {
         font-size: (@size * @basefont) + 0px;
         font-size: @size + 0rem;
         }
  20. Joon
    Permalink to comment#

    A little late but I just read this and created something for Sass that plays nice with the vertical rhythm tools supplied with Compass.

    https://gist.github.com/4526784

    It also contains a rel() function for calculating px to em for everything else.

  21. pixelkai
    Permalink to comment#

    . .. i also don’t get comfortable with the 62.5% value… the browser is set to 100% by default so why not leave it like that and just change the divider to 16 when the result is the same…. :)

  22. Justin
    Permalink to comment#

    I’ve found that functions keep the styles more readable than mixins, so I wrote a few, and I’m pretty happy with the results. Unitize is a SASS partial that turns:

    body {
      margin: unitize(4 6% 2 9px);
      padding: rem(4 6 2 9);
      line-height: rem(18);
      box-shadow: unitize(inset 5 2 #cfc);
      text-shadow: rem(3 3 6 rgba(0, 0, 0, 0.5));
    }

    into:

    body {
      margin: 4px 6% 2px 9px;
      padding: 0.33333rem 0.5rem 0.16667rem 0.75rem;
      line-height: 1.5rem;
      box-shadow: inset 5px 2px #ccffcc;
      text-shadow: 0.25rem 0.25rem 0.5rem rgba(0, 0, 0, 0.5); }
  23. I like the idea of this mixin, but i’m finding that this cuts out using shorthand.

    font: italic 100 2rem/2 $font;

    How can we apply this technique without having to undo the shorthandedness of it:

    font-size: 2rem;
    font-size: 20px;
    font-weight: 100;
    line-height: 2;
    font-family: $font;

    etc

  24. What I use for px2em (can’t remember whom to give creds about that) is:


    $font-size: 1em !default;

    @function em($pxval, $base: 16px) {
    @return ($pxval / $base) * $font-size;
    }

    p { font-size: em(22px) }

  25. yoshua wuyts

    I got a basic Stylus REM mixin going:

     //define default values (best to put this in the default.styl file)  
     base-font-size = 16
     base-line-height = 24
    
     //This is the useful part: it compares the given value to the base values and calculates the correct output
     font-size($fontValue = base-font-size, $baseFontValue = base-font-size, $baseLineValue = base-line-height)
       font-size   $fontValue px
       font-size   ($fontValue / $baseFontValue) rem
       line-height ($fontValue / $baseFontValue) * $baseLineValue
       line-height ($baseLineValue/$baseFontValue) * ($fontValue / $baseFontValue) rem
    
     //Test mixin, adjust the value to see it in action
     p
         font-size(16)
    

    View on github

  26. yoshua wuyts

    Forgot to add the result, here it is:

    p {
      font-size: 16 px;
      font-size: 1 rem;
      line-height: 24 px;
      line-height: 1.5 rem;
    }
    
  27. Thanks for the post. This inspired the following mixin that will take a list of whatever properties with an rem/em value and create a px fallback.

    @mixin rem($properties...){
        @each $property in $properties {
            $rem: nth($property, 2) / (nth($property, 2) * 0 + 1);  //get unitless em/rem
            $px: $rem * 16px;
            #{nth($property, 1)}:$px;   
            #{nth($property, 1)}:$rem + rem;    
        }
    }
    

    Usage:

    .myselector {
        @include rem(font-size 1.5, right .5em, top 1.5rem);
    }
    

    Other:
    Notice the “* 16px” in the mixin? If your base em unit is not 16px, change that.

  28. If anyone is looking for a more comprehensive / refactored version of my mixin above, I hope you find the following useful. It includes a strip-unit() function, an rem() function, and a similar rem mixin to the above.

    //Define 1em = ?px
    $baseline: 16px;
    
    // Remove the unit from a number
    @function strip-unit($num){
        @return $num / ($num * 0 + 1);
    }
    
    //Calculate an rem value from px
    //If $px is an rem or em value, it will be returned as-is, with an rem unit.
    //If $px is a px value, it will be converted to an rem.
    @function rem($px) {
        @if(unit($px) == "rem"){
            @return $px;    
        }@else if(unit($px) == "em") {
            //Assume an em value is an rem -- it's all we can do.
            @return strip-unit($px) + rem;
        }@else if(unit($px) != "%") {
            //Must be a px value
            @return strip-unit($baseline) / strip-unit($px) + rem;  
        }
        @return null;
    }
    
    // Use rem units with px fallback
    // Specify a px, em, or rem value with each property. Unitless values will be considered an rem.
    @mixin rem($properties...){
        @each $property in $properties {
            $value: nth($property, 2);
            @if(unit($value) == "px"){
                #{nth($property, 1)}:$value;    
                #{nth($property, 1)}: rem($value);
            }@else{
                #{nth($property, 1)}:strip-unit($value) * $baseline;    
                #{nth($property, 1)}:rem($value);           
            }       
        }
    }
    

    Usage:

     .myselector {
        line-height: rem(15px); //Pass a px value.
        right: rem(1.5); //Pass a rem, em, or unitless value.
        @include rem(font-size 12px, top 1.7);
     }
    

    Output:

    .myselector {
      line-height: 1.06667rem;
      right: 10.66667rem;
      font-size: 12px;
      font-size: 1.33333rem;
      top: 27.2px;
      top: 9.41176rem;
    }
    
  29. For those interested, I created a family of functions to handle dimension calculations. The rem function and mixin are included.

    Behold: sass-dimension

    A handful of handy functions that provide a common, convenient interface for dimension calculations.

    I’ve also started on a grid system, because it seemed to be a good test case for the dimension functions. I must admit that I’ve not used enough of the other grids to know all their merits or if mine is better, but I’m starting to prefer it over Susy or Foundation (although certainly not production-ready).

  30. Can someone please tell me what the below line of code does?

    @function strip-unit($num) {
    @return $num / ($num * 0 + 1);
    }
    
  31. Scratch my previous question. Just understood what strip-unit function does.

    For me, It is easier to pass a pixel based parameter and have Sass convert it to Rem.
    I can still think pixel but my code outputs Rems.

    body{
        margin: remCalc(10 20 30 40);
    }
    

    This ought to return

        body{
            margin: 0.625rem 1.25rem 1.875rem 2.5rem;
        }
    

    If px fallback are not needed for the website you work on, Karl’s mixin can be shortened to

       @function remCalc($values){
          $max: length($values);
          $remValues: '';
          @for $i from 1 through $max {
            $value: (nth($values, $i));
            $value: $value / ($value * 0 + 1);
            $remValues: #{$remValues + $value}rem;
            @if $i < $max {
              $remValues: #{$remValues + " "};
            }
          }
          @return $remValues;
        }
    

    There’s a similar emCalc function available in Zurb’s Foundation but this one is way more powerful!

  32. That’s exactly what the library I posted does, except you can pass any type of unit to the mixin and it will output a px fallback with an rem value also set.

    In other words, if 1rem = 1em = 16px…

    @include rem(padding 16px, height 4rem, width 10em);
    

    Would output:

    padding:16px;
    padding:1rem; // passed as px
    
    height: 64px;
    height: 4rem; // passed as rem
    
    width: 160px;
    width: 10rem; // passed as em
    

    Notice that px, rem, and em units are passed to the mixin, but only px fallbacks and rem’s dimensions are created.

    I actually renamed the sass-dimension library to sass-unity, because it’s all about having a common interface for calculating/converting units. It has a “unity” function that normalizes a list of units:

    unity(1rem 8px 12px) = 1rem .5rem .75rem
    unity(16px .5rem .75em) = 16px 8px 12px
    

    I know it’s easier to think in pixels right now, because we have for so long, but we might ought to be thinking in scales from the conception of the code. We might ought to be thinking, “This box should be 4 times a variable baseline (16), not always 64 (4×16).”

    It’s been difficult for me to know what the devices will expect of us. DPI is one of the marketing battles, and readability is slightly important, so I think even those of us that haven’t converted have a sneaking suspicion that pixels are a little too rigid; however, I also feel that em’s are too unstable to use for dimensions (mainly height and width). With rem, we can have a pivotal anchor, rather than binding (px) or unpredictable (em).

  33. Jason
    Permalink to comment#

    Based on Karl Merkli’s approach above, this little ditty allows base-10 calculations while maintaining the browser default font-size (the assumed 16 pixel default)…cause math sucks. It also does not require a ‘strip-unit’ directive.

    See the gist.

  34. Permalink to comment#

    Chris I think in usage there is error no ? Should be :
    .font-size(1.3);

    instead of
    .font-size(13);

    Isnt it ?

    Because it looks gigantic in my website if 13. And mixin mutliply by 10…
    Or I am missing something here ! :D

  35. @migswd: to use .font-size(13), you need to adjust the mixins into:

    .font-size(@sizeValue) {
      @remValue: (@sizeValue / 10);
      @pxValue: (@sizeValue);
      font-size: ~"@{pxValue}px"; 
      font-size: ~"@{remValue}rem";
    }
    
  36. Hey guys! I found the rem-fallback mixin really awesome, but it didn’t handle values like “auto”, would turn “em” values into “rem”s, and I’ve no idea how it would handle a percentage. To compensate, I modified the mixin and made it a little more terse. Hope it helps some other folks out there!

    @mixin rem-fallback($property, $params...) {
      $max: length($params);
      $pxValues: '';
      $remValues: '';
    
      @for $i from 1 through $max {
        $param: nth($params, $i);
    
        @if type-of($param) == number and (unit($param) == rem or unitless($param)){
            $value: strip-unit($param);
            $pxValues: #{$pxValues + $value*16}px;
            $remValues: #{$remValues + $value}rem;
        }@else{
            $pxValues: #{$pxValues + $param};
            $remValues: #{$remValues + $param};
        }
    
        @if $i < $max {
          $pxValues: #{$pxValues + " "};
          $remValues: #{$remValues + " "};
        }
      }
    
      #{$property}: $pxValues;
      #{$property}: $remValues;
    }
    
  37. Victor
    Permalink to comment#

    Hey – Correct me if I’m wrong. But shouldn’t the example less mixin be:

    .font-size(@sizeValue) {
      @pxValue: @sizeValue;
      @remValue: (@sizeValue / 10);
      font-size: ~"@{pxValue}px"; 
      font-size: ~"@{remValue}rem";
    }
    

    and

    .font-size(13);
    

    The example uses px but the the mixin is multiplying the value instead of dividing it.

    • Ruth
      Permalink to comment#

      Victor – correct for the less mixin.

      However, WHY are we setting html to 62.5%? I could understand it if we were having to do aritmetic on paper or with a calculator – we are not doing any arithmetic – less, sass or stylus is doing the work.

      All we need to remember is, that no matter what we set our HTML to the pixel value will equal 1 rem.

      16px (100% on html) means 16px = 1 rem

      Therefore, our mixin (for less) becomes:

      .font-size(@sizeValue) {
        @pxValue: @sizeValue;
        @remValue: (@sizeValue / 16);
        font-size: ~"@{pxValue}px"; 
        font-size: ~"@{remValue}rem";
      }
      

      Do we need to make things so complicated? Or am I totally missing the point here?

  38. InitArt
    Permalink to comment#

    My attempt to less mixin using some variables.

    @base-font-size: 100%;
    @rem-fallback: true;
    
    html {
      font-size: @base-font-size;
    }
    
    .rem (@property, @rest...) {
      @length: length(@rest);
    
      .result () when (@length = 1) {
        .fallback () when (@rem-fallback) {
          @{property}:
            unit(@base-font-size / 100 * 16 * extract(@rest, 1), px);
        }
    
        .fallback;
    
        @{property}:
          unit(extract(@rest, 1), rem);
      }
    
      .result () when (@length = 2) {
        .fallback () when (@rem-fallback) {
          @{property}:
            unit(@base-font-size / 100 * 16 * extract(@rest, 1), px)
            unit(@base-font-size / 100 * 16 * extract(@rest, 2), px);
        }
    
        .fallback;
    
        @{property}:
          unit(extract(@rest, 1), rem)
          unit(extract(@rest, 2), rem);
      }
    
      .result () when (@length = 3) {
        .fallback () when (@rem-fallback) {
          @{property}:
            unit(@base-font-size / 100 * 16 * extract(@rest, 1), px)
            unit(@base-font-size / 100 * 16 * extract(@rest, 2), px)
            unit(@base-font-size / 100 * 16 * extract(@rest, 3), px);
        }
    
        .fallback;
    
        @{property}:
          unit(extract(@rest, 1), rem)
          unit(extract(@rest, 2), rem)
          unit(extract(@rest, 3), rem);
      }
    
      .result () when (@length = 4) {
        .fallback () when (@rem-fallback) {
          @{property}:
            unit(@base-font-size / 100 * 16 * extract(@rest, 1), px)
            unit(@base-font-size / 100 * 16 * extract(@rest, 2), px)
            unit(@base-font-size / 100 * 16 * extract(@rest, 3), px)
            unit(@base-font-size / 100 * 16 * extract(@rest, 4), px);
        }
    
        .fallback;
    
        @{property}:
          unit(extract(@rest, 1), rem)
          unit(extract(@rest, 2), rem)
          unit(extract(@rest, 3), rem)
          unit(extract(@rest, 4), rem);
      }
    
      .result;
    }
    
    one {
      .rem (margin, 1)
    }
    
    two {
      .rem (margin, 1, 2)
    }
    
    three {
      .rem (margin, 1, 2, 3)
    }
    
    four {
      .rem (margin, 1, 2, 3, 4)
    }
    
  39. Gus
    Permalink to comment#

    Old topic but perhaps useful to someone else:

    @mixin px-to-rem($org) {
      font-size: $org + px;
      font-size: ($org/16) + rem;
    }
    
    p {
      @include px-to-rem(15);   
    }
    /* Compiled output */
    p {
      font-size: 15px;
      font-size: 0.9375rem;
    }
    
  40. Permalink to comment#

    @mixin rempx($value){
    font-size: $value + px;
    font-size:($value / 10) + rem;
    }
    p{
    @include rempx(16);
    }

  41. kmrsfrnc
    Permalink to comment#

    So the examples assume that you want to set the paragraph to font size 130px?

  42. Great work here, as always, and thanks for your constant inspiration! I have a question about responsive development with rem:

    Snook’s famous article shows changing the root font-size at each breakpoint, but a function like this would have to be adjusted each time, because it uses 1.6 as the base, correct? How can we build something like this that will also allow for changing the root font-size at different resolutions?

  43. Bogdan Marinescu
    Permalink to comment#

    Hi guys just wanted your opinion on this sass mixin, with it you dont have to set the html font-size to 62.5%

    @mixin font-size ($size : 16)
    {
            $sizeRem: ($size / 10) - ( ( ($size /10 ) * 37.5) /100 );
            font-size: $size + px;
            font-size: $sizeRem + rem;
    }
    

Leave a Comment

Posting Code

Markdown is supported in the comment area, so you can write inline code in backticks like `this` or multiline blocks of code in in triple backtick fences like this:

```
<div>Example code</div>
```

You don't need to escape code in backticks, Markdown does that for you. If anything screws up, contact us and we can fix it up for you.

*May or may not contain any actual "CSS" or "Tricks".