Skip to content Skip to footer navigation

Vertical Rhythm with Ems and Rems

Plants on an array of shelves
Update – 1st November 2022

On reviewing this article, I no longer think this is a good idea. The web is built to be fluid, and trying to snap to a grid is too much to wrestle with. Instead, focus on consistent line-height and padding. I've left the article here for preservation.

There are already some tutorials on creating "Vertical Rhythm", most noticeably by Harry Roberts in his articles Single Direction Margins and Measuring and Sizing UIs and Richard Rutter's 2006 article Compose to a Vertical Rhythm.

I mostly wanted to expand on these and cover a few different examples, and more importantly, some gotchas that stopped me picking this up as quickly as I should have. Maybe you've arrived here as a sceptic. Maybe you're scoffing pixel pies and laughing at the complicated em-based maths you'll find here. Well, maybe I wasn't ever that cynical, but I certainly put off looking at ems for a long time.

My Background

I've long resisted moving from Pixels to Ems. I was in the 'I could do without the maths' camp.

That's not to say I was dogmatic about ems; I could appreciate the advantage of bumping font sizes in one go. But being frank I would rather change multiple fixed font sizes than figure out all the maths.

A few things eventually guilted me into giving them another chance, and if you're still bloody-minded, consider the following:

  • If you're designing responsively, you would likely have at least made the mental jump between designing with fixed-width containers to designing with % containers. It might have been a bit of effort to adjust, but it was worth it, right? Then it would help if you also were questioning your beliefs on using fixed pixels for font size.

  • Question when you should ever use fixed pixels. To design responsively is to create relationships between different elements. If your viewport expands, you probably want your main container to expand, albeit with a max-width. When your font size expands, so should your vertical paragraph padding, right? Thinking about these relationships is what convinced me to give ems another look.

  • If you look at the most influential web speakers and writers on Twitter, most, if not all, of them favour ems or rems. Whilst I'm not too fond of web celeb pandering when many of your web heroes hold a particular opinion you should question why that is.

Reading

Read these articles if you want to ponder further...

  1. Flexible Foundations by Trent Walton

  2. Why Ems by Chris Coyier

Establishing a Baseline with P tags

We'll start by just getting our vertical rhythm using just p tags. Nice and easy, hey?

The first thing you need to do is set your font-size to 100%. This does make sure you're starting with the default font size used by browsers, which tends to be 16px. E.g. 100% would equal 16px, 150% = 24px, 200% = 32px, etc.

If you've downloaded the HTML5 Boilerplate as a starting point for your project, this is done for you in their reset. I tend to repeat this rule in the main section of my style.css anyway, just for easy access.

html {
  font-size: 100%;
}

Our next step is to specify line-height. To be honest, line-height is pretty arbitrary. Your typeface and the sense of space in your design will affect your judgement here, but generally, 1.3 to 1.5 is considered optimal.

html {
   font-size: 100%;
   line-height: 1.5; /* Magic Number / Line-height value of 24px */
}

Using these two values, we can derive our baseline figure; what Harry Roberts calls our 'Magic Number'. This is basically what we'll be using to set the rest of our proportions to create consistent rhythm.

In this case, our baseline will be 24px. You get this number by times' your font size by the line-height, e.g. since we are using 100% to get the browser default of 16px, in our case, it would be 16px * 1.5 = 24px. This makes sense if you think about it, we're saying 'times our font-size of 16 pixels by 1 and a half to get the total height for the line'.

The only other thing we need to do is set a margin-block-end property on our p tags. This needs to be a multiple of our baseline, i.e. a multiple of 24px in our instance. So let's set this to 1.5rem (16 * 1.5= 24px).

*FYI: We're using rems just to avoid any nesting complications that initially put people off the em unit, to begin with. If you want to know more about the difference between ems and rems, read Snook's article.*

So that's it; we've created vertical rhythm with p tags. But how do we test this? There are many tools to do this, Dan Eden's baseline.js, for example, but I really like xScope, a Mac design app that you can use for lots of things besides testing baselines. I like it over other tools because you can set a global hotkey to toggle it off and on quickly.

In xScope, you can set a baseline step by going to Guides > Guide Wizard in the menu. Then set the orientation to horizontal, bump Repeat guide to 50 and set moving gutter to the baseline figure we have, i.e. 24. Make sure the gutter has been set to 0, and click 'Create Guide.'

Screenshot of xScope Guide Wizard
You'll see the h2 is tighter to the next paragraph in the screenshot above.
Screenshot of xScope guides
With this, we can see that our p tags perfectly fit a 24px baseline

Establishing a Baseline with H tags

Now we're getting the hang of things, right? Other elements should be easy, but this is where you'll hit gotcha number 1 if you're not paying attention.

Let's say we want to add an H2 tag. What you need to know is HTML5 Boilerplate adds some default margins to H tags, and so does the browser naturally; therefore, we need to set a margin-block-end value for the h2, but we also need to reset the margin-block-start value.

To solve this as we style subsequent elements, you can either reset all top and bottom margins using a group selector to start each project with or add them one by one as you use them. I'd suggest you reset them one by one just in case you miss a style. Otherwise, your reset will kill some safe defaults.

We'll add the h2 to our vertical margin reset and pick our font-size...

/* Reset. Add elements to this Reset as you build up your vertical rhythm */
h2,
p {
  margin: 0 auto;
}

h2 {
  font-size: 2rem; / 32px /
}

You'll see I have put a pixel calculation next to the font-size for future reference. The thing to bear in mind is that once these first calculations have been completed, we never need to worry about them again because in later media queries we just bump the font-size up on the HTML selector.

You get the REM font-size by taking your chosen pixel font-size and dividing it by the initial html font-size we chose. In our case we chose the default 100% (or 16px) for our initial font-size, therefore for a font-size of 32px that would be 32px / 16px = 2rem.

Just so we have another example, if you chose 36px for your h2 font-size, this would be a rem calculation of 2.25rem (36px / 16px).

Gotcha Number 2: Always work with the font pixel size first so you can easily keep things in line with the magic number, e.g. if you arbitrary decide on on a rem figure like 2.2rem, this might give you an odd pixel calculation of 35.2px, which would throw off your vertical rhythm.

To set up the proceeding vertical rhythm, we'll need to add a margin-block-end property of 1.5rem, which falls in line as a multiple of our 24px baseline (1.5 * 16px = 24px)

h2 {font-size: 2rem; /* 32px */
   margin-block-end: 1.5rem;
}
Vertical rhythm lines with h tags screenshot
We'll talk about adjusting h2 proportions in the next section, but you can see from the screenshot above any subsequent p tags will now fall back in line with our vertical rhythm.

Adjusting Rhythm Breaks

Once we have the vertical rhythm working between p tags and h tags, we can play with adjusting the breaks' height.

What I mean by this is, for me, the Heading 2 in the screenshot above feels wrong. The distance between the heading 2 + the previous/next paragraphs is the same. This makes the heading feel disconnected, and you're not sure which paragraph it belongs to. I see this on a lot of websites and dislike it. However, we can change it with a bit of maths.

The simplest way to do it is to add some padding above the h2. We just need to make sure it is a multiple of the baseline. Therefore we can add padding-top of 1.5rem, which is equal to our baseline of 24px (16px * 1.5 = 24px). This pushes our heading 2 away from the previous paragraph while maintaining our rhythm.

Screenshot showing heading 2 pushed away from the previous paragraph

We can also compress the line-height. Again, we just need to make sure the baseline is always a multiple of 24px.

h2 {
      font-size: 2rem; /* 32px */
      line-height: 0.75; /* 24px / 32px */
}
Screenshot showing the h2 is tighter to the next paragraph
You'll see the h2 is tighter to the next paragraph in the screenshot above.

Our maths has all been really clean so far, but if we want to increase our font size, it looks a lot more complicated. Again though, the maths is simple, it just looks complicated.

Here are our maths if we wanted to bump the font size of h2s up to 37px:

h2 {
    font-size: 2.3125rem;  /* 37px */
    line-height: 1.297297297; /* We need to get to a multiple of 24px, therefore 48px/37px. Alternatively we could pull compress the line height by going down to a lower multiple: 24px/37px = .648648649 */
}
Here is a screenshot of the same vertical rhythm, but with a larger h2
Here is a screenshot of the same vertical rhythm, but with a larger h2, as above

Hopefully, this gives you a good few examples of how you can achieve vertical rhythm through rems.

Taking the time to set this up will initially feel like a chore, but will save us maintenance later. For example, if we bump up the HTML font-size to 110% in a subsequent media query, our vertical rhythm will stay intact, with all paddings and font-sizes increasing proportionally. I think fixed pixels appear easier initially, and maybe less complex, but if you value the rhythm and proportion of your design, you should design responsively, relative units are your friends.

Comments

  1. author's avatar dotnetCarpenter says:

    thanks for putting this together.. Probably one of the easiest to follow pieces I’ve seen on rem and vertical rhythm. just one question, why not use units when you declare line-height?

  2. Hi there, glad you liked the post. I’ll have time to do more of these one day! Pixels are absolute units so they destroy any relationship between different elements whereas if line-height is unit-less it’s like saying “2 times the base font size” or “1.4 times the base font size” or whatever the value is, and there is always a dynamic relationship there.

    Another way of putting it is that pixel units don’t “track your font-size”, as Harry Roberts puts it in his article http://csswizardry.com/2011/12/measuring-and-sizing-uis-2011-style/

  3. author's avatar Bart says:

    What about simplifying a bit and just sticking to font-size and line-height for headings. No need for margins or padding. You’ll also get the extra space above heading from the bottom margin of previous p element.

  4. Was just talking about this exact topic the other day, had a quick skim read, looks good! Looking forward to reading over thoroughly.

  5. It’s definitely an interesting concept that I explored last year. Right now I actually don’t think it’s worth the effort of matching the baseline rhythm; it’s too delicate and against the idea of ebb and flow. I still think it’s a useful exercise and in retrospect it’s at least worth keeping margin and padding consistent (I actually tie values to group selectors… or you could use an extend with Sass).

Comments are now closed, please drop me a message if you have any questions