Converting Your Typographic Units with Sass

Byron Houwens
Share

Typography Units Conversion with Sass

This is the updated version of an article first published on March 5, 2015.

Long ago, in the dense mists of the Internet’s past, intrepid adventurers tackled danger in much the same way: sling a fixed 960px layout, fight in a set grid and fire their typography in pixels to ward off evil.

Responsive web design has since changed all that by bringing us out of that dense mist and into an age of enlightenment. And yet, using typography on the web is still a pain at times. With the push from pixels or points to percentages and ems, I find myself continuously having to Google “pixel to percentange conversion chart” or something similar at the beginning of every project, and often even throughout.

In frustration, I finally turned to the power of Sass to forge a new, all-encompassing function in my quest to vanquish these problems, and today you’re going to build that function with me. 

It’ll allow you to convert freely between pixels, em, and percentage values without having to consult a chart every time and, hopefully, alleviate a lot of your headaches in the process.

Setting Things Up for Typographic Units Conversion in Sass

Firstly, it’s extremely important to have a default font-size defined in your CSS. Most browsers will default to 16px, but if your project requires something different, make sure that your CSS knows about it. Also, most boilerplates come with 16px defined as their default value, therefore I’m going to assume this as the default for this tutorial, too.

You then need to decide which units you’re going to support. Since this is likely to be helpful in a print to web environment, or even just a project which starts in Photoshop and ends up in the browser, you’ll be looking at pixels, points, ems and percentage.

You also want to give yourself the option of converting freely between them, so you can already say that your function needs at least three arguments:

@function convert($value, $currentUnit, $convertUnit) {}

The first argument is the font-size number whose unit you wish to convert (for example 16), the second is the unit you’re planning to convert (for example pixels), and the third one is the desired unit you’re aiming for (like percentage). So, as an example, if you want to convert 16 pixels into a percentage value, you would do this:

.foo{
  font-size: convert(16, px, percent);
}

Which will give you:

.foo{
  font-size: 100%;
}

Let’s Beef It

Now, it’s time to tackle the bit that goes in between the braces.

Firstly, you want to be able to tackle pixels, ems, points and percentages, so you’ll need four statements to take care of them all.

If you were using a full-fledged programming language, you might use a switch statement. Since this is Sass, you’ll stick with if statements:

@function convert($value, $currentUnit, $convertUnit){
  @if $currentUnit == px{

    // stuff for pixels

  }@else if $currentUnit == ems{

    // stuff for ems

  }@else if $currentUnit == percent{

    // stuff for percentage

  }@else if $currentUnit == pts{

    // stuff for points

  }
}

You now have an if statement for each possible input unit (whether you want pixels, ems, points or percentages to start with). So this is about 50% of the way there. All you have to do now is throw some awesome stuff into those if statements!

Throwing in the Maths for the Sass Typographic Units Conversion

Okay, so things get pretty mathematical at this point. Assuming you’re working with 16px as the default font-size, you’ll have to convert it into ems and percentage like so:

@if $currentUnit == px{
  @if $convertUnit == ems{
    @return $value / 16 + 0em;
  }
  @else if $convertUnit == percent{
    @return percentage($value / 16);
  }
}

Again, you’re using one if statement per conversion (so one for ems, one for percentage) and then doing a little math to get the desired output. I’m not going to do a case for point values, since these only work with print CSS anyway. 

With ems (and a default size of 16px), you just divide by 16 and add the “em” unit (+ 0em).

Percentages with Sass are a little trickier. You can’t just throw a “%” at the end of the statement like you did with ems, as Sass will throw an error right back (something to the effect of “what are you doing putting that there!”). So here you need to incorporate Sass’s percentage function in order to return a valid percentage unit.

And with that, you have a function that converts pixels into ems or percentages! This is usually enough for a lot of developers, but let’s see how you can extend this function to cover ems to pixel conversion and percentage to pixel conversion:

@else if $currentUnit == ems{
  @if $convertUnit == px{
    @return $value * 16 + 0px;
  }
  @else if $convertUnit == percent{
    @return percentage($value);
  }
}

The math needs to change here for each statement, but that will sort out ems.

Next, here’s how you can convert percentages into pixels and into ems:

@else if $currentUnit == percent{
  @if $convertUnit == px{
    @return $value * 16 / 100 + 0px;
  }
  @else if $convertUnit == ems{
    @return $value / 100 + 0em;
  }
}

Finally it’s the turn of points to pixels, points to ems, and points to percentage conversions:

@else if $currentUnit == pts{
  @if $convertUnit == px{
    @return $value * 1.3333 + 0px;
  }
  @else if $convertUnit == ems{
    @return $value / 12 + 0em;
  }
  @else if $convertUnit == percent{
    @return percentage($value / 12)
  }
}

And you’re done! You’ve created a function that lets you freely convert any value between any unit you want.

To Sum Up

The final function for typographic units conversion in Sass looks like this:

@function convert($value, $currentUnit, $convertUnit){
  @if $currentUnit == px{

    @if $convertUnit == ems{
      @return $value / 16 + 0em;
    }
    @else if $convertUnit == percent{
      @return percentage($value / 16);
    }

  }@else if $currentUnit == ems{

    @if $convertUnit == px{
      @return $value * 16 + 0px;
    }
    @else if $convertUnit == percent{
      @return percentage($value);
    }

  }@else if $currentUnit == percent{

    @if $convertUnit == px{
      @return $value * 16 / 100 + 0px;
    }
    @else if $convertUnit == ems{
      @return $value / 100 + 0em;
    }

  }@else if $currentUnit == pts{

    @if $convertUnit == px{
      @return $value * 1.3333 +0px;
    }
    @else if $convertUnit == ems{
      @return $value / 12 + 0em;
    }
    @else if $convertUnit == percent{
      @return percentage($value / 12)
    }
  }
}

It looks a little daunting, but all it really does is take the initial size, then convert it from the first unit into the second unit, and return the result. The only tough part is keeping track of what calculations to make.

If you want to play around with this function, you can do so in this Sassmeister demo.

As always, feel free to steal, mangle, rearrange and otherwise use this in whatever helps you the most when working with typography on the web.

You could easily expand on the existing function, maybe including something like rem unit conversion, error handling for inputs that won’t work, or setting default units that you use all the time.

 If you have any other awesome ideas for this Sass units conversion function, let us know in the comments section below.