Calculating Ems using Sass

Calculating Ems using Sass

Calculating Ems from pixels is easy. Calculating pixels to Ems is hard. Calculating Ems is nothing more than the quotient of the intended pixel equivalent (IPE) divided by the default font-size of the parent container:

Em = IPE/default font size

The concept is simple, the explanation of it…not so much.

First off: IPE is a term I came up with – it is simply the pixel size you are attempting to set. Let’s look at a simple example using real numbers.

Let’s say your design calls for your <p> tag to be 14px. Most browsers (I think we could say “All browsers”) have a default font size of 16px. Based on the above formula, 14 will be the IPE and 16 will be the default font size. Armed with those two numbers, calculating Ems would be:

Em = 14/16

or

.875em
p{
  font-size: .875em;
}

See, simple right?

Where things get confusing is that now any other Em measurement you apply to the <p> tag now has a default font size of 14px. Let’s return to our example and I will illustrate.

We have our font-size set, but now let’s set the line-height. Our design calls for it to be 16px. Your first instinct would be the following:

Em = 16/16

or

1em

But that would be wrong. Doing this would set an IPE of 14px for your line-height; tighter than what our design requires.

Dealing With Changes to the Default Font-Size

This common mistake happens because we have changed our default font-size for the <p> tag to an IPE of 14px. So now any calculation we make moving forward for the <p> tag needs to be based on a default font-size of 14px:

Em = 14/16

or

1.143em
p{
  font-size: .875em
  line-height: 1.143em
}

It’s the change in default font-size that can make working with Ems so confusing. Going back to pixels once you have your Ems set is also a challenge primarily because you don’t have the benefit of knowing the default font-size of the element you are working with without doing a little homework.

You might have some reservations to using Ems because of calculations and commenting your code in such a way that you can easily see what the IPE of the Em is.

I had the same concerns when I began using Ems in my designs – and my code comments were no less confusing:

.my-element {  
  font-size: 1.125em; // 18px/16px  
  line-height: 1.44em; //24px/18px … remember the parent element is now 18px
}

And I eventually would get lazy, and the above would turn into:

.my-element {  
  font-size: 1.125em; // 18px
  color: #fffff;
  font-family: serif;  line-height: 1.44em; //24px
}

At which point, it became a pain to maintain.

There had to be a better way.

Enter Sass Functions

I love Sass. It has completely changed the way I relate to and write CSS.

I used to hate writing CSS mostly because I was pretty horrible at it – tons of redundancy, unnecessary properties, and a liberal spattering of commented-out code left me with some horrendously bloated files that were agonizing to maintain.

If you are new to Sass, I cannot give a higher recommendation for Dan Cederholm’s (@simplebits) book Sass For Web Designers. If you are a Sass veteran, I cannot give a higher recommendation for Dan Cederholm’s (@simplebits) book Sass For Web Designers. That’s not a typo… you need to buy that book.

Sass simplifies a plethora of issues when writing your CSS. Variables and Mixins help prevent the redundancy that creeps into every project and allows for you to have some fairly robust templates at your disposal allowing for faster and more efficient starts to your projects.

But one of the more powerful features of Sass is the ability to use functions to automate calculations – specifically, calculating Ems.

What I set out to create was a simple function that would allow me the ability easily and intuitively converts pixels into Ems and is able to easily and intuitively allow me to maintain that code later by showing the default font-size in all measurements.

Calculating Ems with a Sass Function

Here is what I came up with:

@function calc-em($pixels, $context: $browser-context){  
  @return ($pixels / $context) * 1em;
}

Functions in Sass are similar to functions you would write in any other scripting language (think JavaScript).

First, we declare the function:

@function calc-em(){}

Now let’s require some parameters to be passed when the function is called:

@function calc-em($pixels, $context){}

$pixels will be our IPE and $context will be our default font-size. But passing the default font-size all the time can be a pain, so let’s create a variable and use it as a default variable if the $context variable isn’t passed:

$browser-context: 16;
@function calc-em($pixels, $context: $browser-context){}

: $browser-context basically says, “if $context is blank, use $browser-context”

We have all the numbers we need, now all we need to do is perform the calculation and return the quotient:

@function calc-em($pixels, $context: $browser-context){  
  @return ($pixels / $context) * 1em;
}

Why are we multiplying the quotient by 1em? So we can output the result in proper CSS syntax.

So now something like this:

.section-leader {  
  h2 {    
    font-size: calc-em(50);    
    line-height: calc-em(48,50);  
  }
}

compiles neatly into:

.section-leader h2 {  
  font-size: 3.125em;  
  line-height: 0.96em;
}

This function can be used to calculate Ems for things such as margin and padding as well:

.section-leader {  
  h2 {    
    font-size: calc-em(50);    
    line-height: calc-em(48,50);    
    margin: calc-em(20,50), calc-em(50,50);  
  }
}

Which compiles into:

.section-leader h2 {  
  font-size: 3.125em;  
  line-height: 0.96em;  
  margin: .4em, 1em;
}

And because you only edit your .scss files (Sass), maintenance is a breeze because you are abstracted from the calculation and simply see the intended pixel equivalent and default font-size.

For more information on Ems, Kezz Bracey  (@KezzBracey) has a great article Comprehensive Guide: When to Use Em vs. Rem that gets into the meat of flexible units of measurement.

Do you have any cool functions you are using with Sass? If so, share them with us!


We are all about sharing!

Feel free to share this content by clicking on the icons below:

Pin It on Pinterest