Join Val Head for an in-depth discussion in this video Sizing your type: Pixels, ems, and rems, part of Responsive Typography Techniques.
There are a number of units we can use to measure things on the web. Things like Pixels, Ems, and even Rems. All of these units can be applied to the size of our type. In this tutorial we'll define what each of those measurements are and what they're best at when it comes to sizing our type. Picking a unit to size your type with, may seem like a mundane or unimportant thing. Let's be honest, it might even sound a bit boring but the method you pick for sizing your type can affect your entire layout. So it's a really important decision. Let's take a look at the three options we'll cover in this tutorial, Pixels, Ems and Rems.
Sizing your type in pixels generally seems like the most absolute. We all generally have an idea of how big a pixel is in our head. And most graphic design software like Photoshop offers pixels as a sizing option for text in our mock ups. For those reasons, pixels tend to feel like they give us more control. In our example files, I have a page with all its text size in pixels for us to look at. We'll open the screen.css file in the pixels folder to take a look at how everything is sized. A quick look at our CSS shows we have H1s, H2s, H3s, and paragraph text all set in pixels.
We can see we have our font size set in pixels here for our H3s, as well as our H2s and even a pixel size set on our body tag. The document's body has a font size of 16 pixels, and the titles are sized at values that go up from there. This seems like a pretty solid solution, but there are two major drawbacks to sizing our type in pixels. IE's text size tool in older versions of IE will not resize text sized in pixels, no matter what setting the user chooses. This can be an accessibility concern.
Using pixels to size our type is also not very flexible. If we wanted to make all our text bigger, we would have to go and assign a new pixel value to each element that we've set a font size on. In our example, this would mean the H1's, the H2's, the H3's, and the font size we set on our body tag. And that's just for a simple example page. If we wanted to change the size of our text multiple times based on user input or the width of our window things can get really complicated fast. Ems on the other hand our relative unit of measure which makes the much flexible then pixel values.
They are more content aware and resize more easily than pixels, so let's move over to Coda and edit our CSS to change our pixel value over to Ems values. To change our example page over to using Ems for type sizing, let's first set our body's font size to a more flexible base line of 100%. Using 100% here means that we want the browser to use its default font size. We don't have to use 100% to use Ems but I personally find it a good and a very flexible place to start. Also, our browser's default text size is usually approximately 16 pixels, so that's something we'll need to reference in a minute.
With that in place, our next step is to convert our other font size values from pixel values to Em values. To do that, we're going to use a common equation in responsive web design. And that is, Target / Context = Result. Let's put that into practice with the rules for our H1. The font size for our H1 is currently set to 55 pixels, so our target is 55 pixels. Our H1 exists within our document's body, which has a font size of 100%, or approximately 16 pixels. So that's our context, that makes our equation, 55 / 16. And that equals 3.437.
I find adding little comments like this to explain the math you've used, is really helpful when you go back to edit your CSS later. So let's put that number in for our font size, and finish it off with a unit of Ems. Now we have our H1 size with a relative unit of Ems. Since we set our font size to Ems, it would make sense to convert our margins and line heights to Ems as well, to really take full advantage of this relative sizing and this is where Ems get a little bit tricky. Our H1's line height is currently set to 55 pixels. That's the same value we had for our font size.
However, the context of our line height is different than it was for the font size. The context of our line height is the font size itself. So our equation would look like this. Our target of 55 which exists in the context of 55 pixels. Since 55 pixels was our original font size value that we converted to Ems. And that, of course, equals 1em. We can replace our line height with that value here. Our margin works in a similar way, where the context is, once again, the font size. So we can set this 55 pixels to 1em as well.
Because the target of the 55 pixels for our margin exists within the context of our 55 pixel font size. We'll continue on like this and set the font size, line height, and vertical margins for all the other elements in our CSS file. As I go along, I'll put in the comments for the equation that I'm using to arrive at each new value and then replace it for the font size line header margin that I'm working on. So our H3 font size will be 1em and since our margins are 16 pixels as well, we'll set that to be 1em as well.
And as a last step, we'll do these same changes for our drop cap as well. Now that we have all our font sizing margins and line heights set to Ems, changing the size of all our type globally becomes a really easy task, and that's a huge benefit of relative sizing. Let's take a quick look at our current page in the browser right now for reference. So, this is what our page looks like right now. To make all our font sizing and spacing increase globally, we can change our body font size to 120%.
So let's go back over to Coda and make that change. Up at the top, our body's font size is currently 100%. We'll change that to 120%, changing just one property. If we save our CSS and go back and preview our page again, all of our font sizing and spacing has increased by 20% just by changing that one line. Of course there are some drawbacks to sizing with Ems. For example, your context can change. As you saw with our example, sometimes our context was the size of the body text for things like the actual font size But when it came to things like line height, our context was the font size itself.
If you start nesting elements together and they each have font sizes set in Ems, that can get very complicated. Keeping track of the context can get confusing. On a related note, Ems can be potentially less portable due to the change of context. For example, if you moved a paragraph from one container to another container, it's context and the size of that context could change, which means you'd have to redo your math to figure out the Em value, and that might not always be such an easy thing. And that brings us to Rems, which is one of the newest units we have available to us.
They are relative units of measure, just like Ems, but they are less dependent on context. They are a part of the CSS3 spec. So they haven't been around as long as Ems and pixels. Rems are not affected by the context like Ems. Rems are always sized based on the base font size of the root of the document. That sounds a bit confusing, but what it means is that Rems are always based off the font size you set on your HTML element. And that can be a lot easier to use. I'll show you what I mean. Let's go back to our pixel based font size example, and convert those over to Rems.
So, back to our pixel based style sheet in Coda, we'll make a few changes to set the values in Rems instead of pixels. The root of our document is the HTML element. We haven't actually set any styles for that in our CSS file yet, so let's add a rule for it. To use Rems, we need to set a default font size within this rule, and just like when we were working with Ems, let's start with the browser default of 100%. And remember, in the case in most browsers, 100% is approximately equal to 16 pixels.
This will make all our conversions, even those for line heights and nested elements, very straight forward. We'll continue by removing the font size declaration off of the body, since we're doing that in the root HTML element instead. And then we'll move down to set a new font size for our H1. Since Rems are also a relative unit, we need to use that same equation to determine what the number will be. So in this case, we know that our target is 55 pixels. And because we're using Ems, no matter what we'll be dividing by 16, because that's the approximate pixel value of the 100% we set on our HTML element.
So 55 / 16 = 3.437. But, in this case we're going to set the unit to REM. So far this works exactly the same as Ems. But here's where it gets a little bit different. Let's set the line height for our H1 in Rems. We know that our target is 55 pixels. But because we're using Rems, our context is always going to be that approximately 16 pixels. So this will also be 55 divided by 16, which will of course, give us the exact same value we had above. And that right there is the main advantage of Rems.
The fact that everything is based off the same context, makes our math a whole lot easier. And it also makes it easier to follow later. So that all sounds great, but what's the catch? Browser support is unfortunately the catch for now. Currently, Rems have decent support, but not 100% support, especially with older browsers, which are still a necessary evil for most of us. If we take a look at the support table on caniuse.com, you can see that Rems are supported on pretty much everything except things like IE8 and Opera Mini.
Opera Mini may not be a big concern for most of you, but IE8 probably is. So, in order to use Rems, we'll need to set a pixel measurement as a fallback. If you're using something like Sass or other pre-processors, there's some mix-in you can use to do this fairly painlessly. Otherwise, you'll have to do it by hand. So to summarize, pixels are absolute and easy to convert from things like Photoshop, but they lack the flexibility we often need in responsive design. Ems are flexible and proportional, but their dependence on an element's context can get tricky at times.
Rems are also a relative unit and are less context dependent but they're a bit new and not widely supported so you have to make sure you use a fallback with Rems.
- Deciding between self-hosted and hosted web fonts
- Sizing your type with pixels, ems, and rems
- Applying and choosing a typographic scale
- Creating a font stack
- Maintaining line lengths
- Using media queries to set natural typographic break points