Create a gist now

Instantly share code, notes, and snippets.

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 }
}

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?

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/)

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

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

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