Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PX to EMs conversion in Sass
/* See http://mrdanadams.com/2012/pixel-ems-css-conversion-sass-mixin/ */
/* Default font size in pixels if not overridden. */
$baseFontSize: 16;
/* Convert PX units to EMs.
Ex: margin-right: pem(16);
*/
@function pem($pxval, $base: $baseFontSize) {
@return #{$pxval / $base}em;
}
/* Used to convert PX to EMs for multiple properties or values or both.
$base is an optional measurement that allows making measurements relative to the parent font size rather than the current. Also accepts a list of lists (instead a list of values) for properties that accept multiple lists of values. Only numbers of converted; everything else is passed through.
Examples:
@include scale(line-height, 30)
@include scale(line-height, 30, 16)
@include scale(width height, 125);
@include scale(padding, 0 25, 16);
@include scale(text-shadow, (#0d6e28 1 1) (#777 0 0 2), 16);
@include scale(box-shadow, (inset 0 0 0 1 #2a9022) (inset 0 0 3 #459966), 16);
*/
@mixin scale($props, $sizes, $base: $baseFontSize) {
$values: ();
$sublists: false;
@each $s in $sizes {
/* unwrap lists for values that have multiple list of values such as text-shadow */
@if type-of($s) == list {
$sublists: true;
$vv: ();
@each $ss in $s {
$vv: append($vv, if(type-of($ss) == number, #{$ss / $base}em, $ss));
}
$values: append($values, join((), $vv));
} @else {
$values: append($values, if(type-of($s) == number, #{$s / $base}em, $s));
}
}
$value: join((), $values, if($sublists, comma, space));
@each $prop in $props { #{$prop}: $value }
}
@chris-pearce

This comment has been minimized.

Copy link

commented Feb 11, 2013

This is a great mixin, cheers! I created another mixin for rem units also which is pretty much identical to the em mixin but you don't need the $base argument as rems are always calculated to the base font size so you just hardcode that into the mixin e.g. #{$ss / $base-font-size}rem.

One thing I'm struggling with though is I need to provide a px fallback for browsers that don't support rem e.g. IE 8, to do this the division needs to be removed and rem replaced with px in both lines 34 and 38 above, so like this:

L34: $vv: append($vv, if(type-of($ss) == number, #{$ss}px, $ss));

L38: $values: append($values, if(type-of($s) == number, #{$s}px, $s));

Any idea how I could work that into the mixin?

@arxpoetica

This comment has been minimized.

Copy link

commented Mar 11, 2013

I've thought of this before. It'd be nice if some preprocessing could go on in Stylus so it know inheritance based on markup, so one wouldn't have to include context. But that's kinda' a pipedream. (I s'pose one could utilize Phantom.js to that end http://phantomjs.org/)

@GrantCuster

This comment has been minimized.

Copy link

commented Apr 1, 2013

@crite70 I had the same thought, am currently going forward with:

 @mixin prem($prop, $pxval)
      #{$prop}: #{$pxval}px
      #{$prop}: #{$pxval / $baseFontSize}rem
@bluehiveinteractive

This comment has been minimized.

Copy link

commented Jul 2, 2013

Curious...what are you guys setting for your font-size in your sass for html/body for this?

I just dropped _pems.scss into my sass folder and imported it in my style.scss and I set some text

p { font-size: pem(16);

I inspected it in Chrome and it says font-size: 1em;

however its obviously much larger than 16px

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.