Sunday 21 December 2014

Taking the “Erm..” Out of Ems

I'm going to make a sweeping statement; pixels have no place in web design. There's only one reason you're still relying on pixels – and that's because you haven't yet gotten the hang of ems. Let's change that!
demystifying-ems-fight
Decorative M courtesy of Frances Mcleod - winner of TypeFight #34
When we build websites, we need to tell the browser how “big” stuff is: “this heading is so big”, “this container is yay high”, “this form is wider than that”, it's how we layout a page. Pixels have always made perfect sense as the chosen unit of measurement; we're outputting to a screen, so what else would we use?!
However, it turns out that pixels are inherently inflexible. And it turns out that being inflexible isn't great for the web.
Oliver Reichenstein stated a long time ago: “The Web is 95% Typography”, but it's taken a good few years for people to get on board with the idea. Content and users; they are our priorities as web designers, and typographic design helps us meet those priorities.
Browsers display body copy at a default size. On desktops this is generally 16px, mobile browsers vary. Users can change this default, depending on what they prefer.
demystifying-ems-browser-settings
Often, web designers will use CSS to cast the base font size in stone..
demystifying-ems-font-size-12px
..preventing the user from tailoring their own reading experience, ultimately making the content less accessible.
Lesson one is in handing power back to the user. Don't prevent users from setting their own type size, but make sure you begin on a level playing field. Set your base font to 100% of the browser default:
demystifying-ems-font-size-100
then we can work from there.
We still need to define how large our various typographic elements appear, especially if we've used a CSS reset technique to remove all default sizing. A fairly typical modular scale would look something like this:
demystifying-ems-modular-scale
These figures have been used for centuries, calculated in order to optimize proportions, without having to physically manufacture too many of the blocks used in printing. There's all kind of clever mathematics which justify scales like this and I'm sure you can appreciate that this range is pleasing to the eye too.
We would translate this scale to our own typography by applying CSS a bit like this:
demystifying-ems-modular-scale-pixels
However (as we've said already) using fixed pixel values is inflexible, so let's rectify that..
An em is a unit of measurement. Just like pixels, ems can determine the size of elements on a web page. Unlike pixels, which are absolute, ems are relative to their parent's font size, which is where a lot of confusion lies.
1em is equal to the inherited font size. If the font size of a <div> is set to 16px, 1em within that <div> is equivalent to 16px. If the font size of that <div> changes to 20px, 1em within that <div> is equivalent to 20px.
Ems get their name from printing. Precisely when the term was first used is unclear, but as the uppercase M (pronounced emm) most closely represents the square printing block on which printing letters were placed, it came to lend its name to the measurement. Whatever the point size of the font in question, the block of the uppercase M would define the Em.
An em is usually a touch larger than the letterform, but you get the idea.
demystifying-ems-1-em
An uppercase M in Calendas Plus - the surrounding square is 1em high, 1em wide
We've already started to set our typographic scale in pixels, so how do we convert that into ems? A simple calculation, which expresses the desired font size in relation to the body font size:
demystifying-ems-equation
Using the body size we assume to be 16px, aiming to convert our 36px <h1>, we get:
demystifying-ems-equation-result
Here's how our scale is converted, using the method above:
demystifying-ems-modular-scale-ems
Some of these values can get a little complex, but don't be afraid to be as precise as possible with the decimal places. Browsers will always do their best to render the exact values.
Tip: It's often useful to make a note in the comments, to remind yourself how you calculated each em value.
The number one biggest grumble people have with ems comes from complications which arise from cascading. An em value is relative to its nearest parent's value, which can accidentally mess things up if you're not paying attention. Take a look at the following css, which aims to get anchors and paragraphs sized equally:
demystifying-ems-p-a
Now take a look at this innocent piece of markup:
demystifying-ems-bieber
As you'd expect, all appears well in the browser. Both the paragraph and the anchor are displaying at 1.2em, relative to the body font size (1.2 * 16px = 19.2px).
demystifying-ems-markup-good
However, if we were to introduce a second anchor within the paragraph, let's see what happens:
demystifying-ems-markup-bad
The anchor within the paragraph is still sized at 1.2em, but that's now relative to the parent paragraph, which is already 19.2px - (1.2 * 19.2px = 23.04px). This gives us extra large anchors in some parts of our page; hardly desirable.
Note: Nested list items in navigation menus are a classic example of where cascading can get out of control - watch out for that one.
There is no fix for this; the last thing you want to do is add an extra rule to decrease the size of anchors which happen to be in paragraphs - that's a one-way ticket to Migrainesville. In order to keep your CSS and HTML maintainable, it's important to Keep It Simple™.
  • Keep your markup simple and modular.
  • Define your ems clearly and in a restrained fashion - don't go throwing them all over the place.
  • Try to restrict font-sizes to typographic elements; be cautious of applying font-sizes to structural elements.
That should help! Using Ems does mean that you'll have to think quite hard sometimes, but doing so will force you to clean up your act and be efficient in your coding.
Rems are useful and behave in exactly the same way as ems, without the cascading. Every Rem you define is relative to the body font size. Support is nowhere near as good however, so IE8 and older will need a pixel-based fallback.
We've covered the CSS font-size property; a sensible first step into using ems, but now let's look at line-height. If ever there was a property which screams "don't use pixel values", it's line-height. The line height (discussed during an earlier article in more detail) of a typographic element should always be relative to the font-size. If you have a heading whose size is set in ems, but whose line-height is set in pixels, you could end up with ugly overlapping and a poor visual relationship in general.
There's no fixed rule for how large line-height should be, but 1.5em is a reasonable value to try out and will make your typography pleasantly readable.
demystifying-ems-line-height
In this case, 1.5em is 1.5 * 18px which is 27px
Tip: Take a look at Bryan Gruhlke's suggestion in the comments for using unit-less values with line-height..
Note: Things can get complicated if you're trying to set a baseline grid with ems, but that's a topic for another article.
Once you get into the mindset of keeping your layout flexible in terms of the font size, you'll find you rely on pixels less and less for laying out elements on the page.
If we're talking about fluid layouts, you should be using % values to determine the width of any given element. Pixels should be nowhere to be seen when determining horizontal dimensions.
Vertical spacing can be achieved very easily with ems; again, it's a question of being clean with your markup and styling. Consider restricting margins to the bottom of your elements, so as to make managing vertical rhythm easier.
If you need to define a height (which can be tricky in flexible layouts) use ems too. Perhaps you're building a navigation and need to define the height of the menu links - they should grow and shrink with the font size.
Rounded corners on a button? Set the border-radius using ems, so everything scales seamlessly.
demystifying-ems-button
Take a look at this Codepen for a more visual example of what I'm talking about here
Text shadow, box shadow, ditto.
And if you need to change the size of everything under certain circumstances, like smaller viewports? Alter the base font size of the body in the appropriate media query body { font-size: 90%; } and wham! Your whole site scales in the time it takes to hit enter.
Like all excellent scientific rules, there has to be an exception to prove it. In this case, I can think of one good scenario where you may need pixels; borders. If you define a border width (or the height of a horizontal rule) in ems, it may find itself being calculated so small that the browser can't render it.
In this case, you simply won't see it.
demystifying-ems-hr-demo
Take a look a this wee demo
For horizontal rules, you may have styles a bit like this:
01
02
03
04
05
06
07
08
09
10
hr {
    height: .02em;
    border: none;
    background: white;
    margin: 2em 0;
    outline: none;
    display: block;
    clear: both;
    width: 100%;
}
In order to prevent it disappearing when the body size is too small, you could add this:
1
min-height: 1px;
There. A pixel. Dangit.
Border widths cannot have a minimum value (sadly) so a similar backup in that case isn't possible. Instead, you could use the border width values of thick, medium and thin, although these values don't scale with font-size any better than pixels do.
Advertisement
Start using ems today! Your content is typographically grounded, whether you realise it or not. Referring back to pixels, converting figures and thinking in terms of fixed layouts isn't even necessary. Begin thinking in ems and you'll soon forget pixels altogether.
If you can think of a situation where you simply can't use ems, I'd love to hear it in the comments!

No comments:

Post a Comment