Last Updated: September 09, 2019
·
8.139K
· roybarber

PX to EM Conversion in Sass/Compass

Heres a handy PX to EM conversion function for SASS, also works if your using compass as a helper.

// Enter a base pixel size in px (without the px)
$basepx: 16;

// Convert PX to EM global function
@function pxtoem($px, $basepx){
    @return ($px/$basepx)+0em;
}

Then on a class or element you can use:

h1 { font-size: pxtoem(36, $basepx); }
h2  { font-size: pxtoem(28, $basepx); }
h3  { font-size: pxtoem(22, $basepx); }
.class { font-size: pxtoem(14, $basepx); }

or on your media queries:

@media all and (min-width: pxtoem(600, $basepx)) {
    .class {}
}

would then churn out the em value instead of px in you compiled stylesheet!

Any questions?

Enjoy!

3 Responses
Add your response

Cool!

over 1 year ago ·

I use something similar, and set my $base-font-size in my _base.scss with all my other config variables. I set the $basesize in the function to be equal to that variable by default, which avoids having to declare it everytime I use the function. The nice thing is, you can pass a new value there when the context needs to change – say, for when you want to control the font-size of nested elements.

My functions go like this:

/* Turn numbers with units into unitless numbers: https://github.com/nex3/sass/issues/533 */
@function clear-units($value){
    @if type-of($value) == "number" {
        @if (unitless($value)) {
            @return $value;
        } @else if unit($value) == "em"{
            @return $value / 1em;
        } @else if unit($value) == "px" {
            @return $value / 1px;
        } @else if unit($value) == "pt" {
            @return $value / 1pt;
        }
    } @else {
        @warn "Not a number value: #{$value}";
        @return $value;
    }
}

/* Easy little function to do the math of pixel to EM conversion for us. Needs a base-font-size set in _base.scss */
@function px2em( $pixel, $base-size:$base-font-size ) {
    /* Remove units for easier math. We are converting to EMs anyway */
    $pixel: clear-units($pixel); 
    $base-size: clear-units($base-size); 
    @return #{$pixel / $base-size}em;
}

I'm not sure why those @else declarations got wrapped in an anchor when the code snippet rendered...

It should also be noted that this little function is great for any pixel-to-em conversion, so there is no reason why you can't do this: @media (max-width: px2em( 480px )) { }

over 1 year ago ·

Good Stuff. Worked perfectly.

over 1 year ago ·