Adventures in Vertical Rhythm

Vertical rhythm is the spacing pattern between elements on the page: the sum of design decisions around font size, line height, margins, and padding. The goal of having good vertical rhythm is to provide a comfortable and engaging reading experience for our users. The challenge is, how do we know when we’ve achieved it, besides our design instincts? And how do we maintain the rhythm when the content changes?

When done well, the result is invisible to the reader. Someone browsing our website doesn’t think, Wow! What amazing vertical rhythm! The different fonts totally work together to create a harmonious reading experience for me! They just... read the page and carry on with their life.

When the vertical rhythm is off-beat, though, it gets in the way of their experience. They may have a harder time tracking where they are in the page, which phrase they last read, or distinguishing one section from the next. Poor rhythm slows readers down and increases their cognitive load. The more work a person has to put in to follow along with what we’re saying, the more frustrated they’ll get, and the more likely it is we’ll lose their attention altogether.

What good looks like

The thing is... it’s not always so easy to point to something and say, “this definitely has bad vertical rhythm”, without an example of the same text with improved spacing.

A Modest Proposal, with browser default spacing

A Modest Proposal, with vertical rhythm applied

The first example isn’t obviously terrible, but by comparing the two examples side-by-side, we intuit that one feels better to read than the other. What properties give us that feeling?

The sense of rhythm comes from repetition. Using a repeated spacing pattern — through the combination of font sizes, line height, margins, and padding — guides readers through content without getting in their way.

Font size

Font size has the most noticeable impact to comfortable reading. Too big, and readers slow down, or focus more on individual letters than on words. Too small, and it can cause eye strain.

What’s comfortable sizing for one reader will be uncomfortable for another, which is why it’s important to utilize relative sizing for typography. By using relative units, the font size becomes a suggestion for how best to experience the content, instead of a hard requirement.

Choosing font sizes

Different elements of the page will require different sizes to emphasize hierarchy or importance. We need to choose sizes that are different enough from each other so that the reader can actually detect those changes.

Introducing a modular scale is one way we can create a palette of different enough font sizes. To generate the scale, we must choose a base font size that will be used for body copy, and a ratio for generating multiples of the base size.

Modular scale demo

Choosing a base font size is a very important design decision: not only will it be the basis for our modular scale, it will ultimately drive the vertical rhythm for the entire application.

Note that the browser default size for body copy is 16px for most browsers; thus, 16px = 1rem. If 16px is too small to function as a default size for our chosen typeface, choose a size greater than 1rem that works for the body copy. For example, if our chosen typeface looks best at 18px, then we’d use 1.125rem as the value for the font-size property.

Choosing a modular scale ratio

Each subsequent size is a called a step in the modular scale, and is generated by multiplying the previous step by the chosen ratio. Following the previous example, if we were to choose 18px as our base font size, and 1.5 as our modular scale ratio, the first five steps in our modular scale would be: 18px, 27px, 40.5px, 60.75px, 91.125px.

Some ideas from the modular scale site on how to pick a ratio:

Ratios can be chosen carefully and meaningfully, drawing inspiration from the history and character of a typeface or other elements in a project. Billy Whited gave several tips for choosing a scale, and Nathan Ford wrote about choosing ratios as part of deriving layout from your typeface. Owen Gregory thinks we might look to musical scales for better harmony. Or, choosing a ratio can be more simple...

The smaller the ratio, the closer together the steps. We’re also implicitly choosing the number of steps in addition to the ratio, because we need to have enough sizes to choose from to support our information architecture. This sounds quite technical, but choosing the modular scale ratio is really more of an art than a science.

Leading, or line height

Leading (pronounced ledding) is the distance between the baselines of two consecutive lines of text. This term comes from metal type, where a strip of lead would be inserted between lines to ensure letters didn’t run into each other.

In CSS, the closest property is line-height, which works a little differently. It is the distance from top to bottom of a single line of text, inclusive of extra space. The line height is the sum of:

  • the height of the typeface itself at a given size
  • further space above and below the text, based on the ratio supplied

Some text set at size 16px with a line-height of 1.5 (that is, 24px) means there’s about 4px of spacing both above and below the text.

Choosing the base line height

Line height is best defined using unitless ratios to make changes in font size easier to maintain. A comfortable range is generally somewhere between 1.2 and 1.8 times the font size, depending on the characteristics of the typeface. The bigger the ratio, the further apart the lines. If the lines are too far apart or too close together, readers will have a hard time tracking where they are in the paragraph. A certain amount of proximity needs to be maintained so that phrases within a paragraph appear like related ideas, and not independent elements.

Note that the line-height ratio doesn’t need to have any relation to the modular scale ratio.

We also don’t have to use the same line height ratio for all text on the page. Sometimes we want headers of larger font sizes to have a smaller ratio in order to maintain proximity between multiple lines; we can let our design instincts guide us to make appropriate choices. But the base line height ratio that we will use for body copy will affect the entire structure of the page, so we must choose it carefully.

Dealing with variations in size and content

Headings, subheads, block quotations, footnotes, illustrations, captions and other intrusions into the text create syncopations and variations against the base rhythm of regularly leaded lines. These variations can and should add life to the page, but the main text should also return after each variation precisely on beat and in phase.

from The Elements of Typographic Style

How might we deal with such variations? As I’ve alluded, our choices of base font size and base line height give us the key we need to maintain vertical rhythm, no matter how content is arranged on the page. This key is the rhythm unit.

Rhythm Unit

The base font size, multiplied by the base line height ratio. All components on the page should have a height divisible by the rhythm unit.

This height should be inclusive of vertical margins and padding, so that we maintain the repeated spacing pattern established by our body copy. In my research, I’ve seen some advocating that the rhythm unit should be half the base line height, to provide greater flexibility in the design — this is another design decision for the team, but the point remains that the rhythm unit should be derived from the base line height.

Setting vertical margins and padding

Let’s say our base font size is 16px, and our line-height is 1.5. We’re adding a button into our page. How tall could our button be?

The rhythm unit in this scenario is 16px × 1.5 = 24px. So, to maintain the rhythm of the page, the total height of the element should be a multiple of 24px. In CSS, margin is never included in height calculations, and padding is only included if box-sizing: border-box;, so we should be sure to take that into consideration. We should also watch out for possible margin collapsing when deciding on a solution.

There are a few ways we could ensure the button size is based on the rhythm unit: one possible solution could be that the height of the button (inclusive of padding and borders) is 36px and the bottom margin is 12px.

Putting it all together

Vertical rhythm is the sum of design decisions around font size, line height, margins, and padding. In many projects, these choices tend to be magic numbers, and while it isn’t necessary to scrutinize the anatomy of different typefaces in order to choose the “most optimal” values, in the end, we still have to maintain these choices in code.

So far, we’ve identified and defined these key factors for maintaining vertical rhythm:

  • rhythm unit
  • modular scale
  • relative sizing

I combined these ideas in a CodePen showcasing a unified typography framework:

The goal of the framework is to abstract away as many calculations as possible, without needing to manually revisit the CSS for a bunch of different components if we make changes to one of the key factors.

Here’s the SCSS code for getting content back in rhythm, no matter how it varies:

@function rhythm-offset(
    $target-font-size,
    $line-height-ratio,
    $multiple: 0
) {
    $line-height: $target-font-size * $line-height-ratio;
    $offset: $rhythm-unit - ($line-height % $rhythm-unit);
    @return $offset + $rhythm-unit * $multiple;
}

This function calculates the line height of the target element, and uses the modulo operation to find out how far the target element has deviated from the rhythm unit.

For example, let’s say we’re trying to figure out how much margin to add to an h1 element that has a line height of 54px. If our rhythm unit is 24px, 54px % 24px = 6px, so that means the total height of the h1 is 6px off beat.

To get us back on beat, we can add 18px (the rhythm unit minus the 6px) in margins. If, for whatever reason, 18px isn’t enough space, we can add multiples of the rhythm unit after accounting for the offset.

The primary issue with this calculation is that it doesn’t take the number of lines into consideration. If the h1 were two or three lines long, that could potentially throw the rhythm off. It’s quite a challenge to account for dynamic content that deviates from the natural rhythm of the body copy, and it isn’t really worth the additional complexity. It’s more important to have maintainable code and a flexible, responsive design, than absolute conformity to the rhythm.

Validating vertical rhythm

In my example above, the baseline grid can be toggled to view how the content follows the rhythm. This is fine for a CodePen, but how might we make this more practical for a real project?

This seemed like an interesting use case for automated visual regression testing. We could inject some CSS like Basehold.it at the time the tests run and take screenshots with the baseline turned on, so we can continuously validate our vertical rhythm.

I decided to try this out on this very blog, to see how the typography framework would fare in a more realistic scenario. My blog doesn’t have a ton more going on than the CodePen, but I’ve added things like blockquotes, code snippets, and the occasional image which interrupt the rhythm. I also got to see how my responsive and adaptive design fared against the grid. I immediately ran into the problem of some posts having longer headlines than others. The calculation of the rhythm offset turned out to be less of an exact math — it didn’t necessarily follow that 2 lines of heading was exactly equal to 2 times the leading, which meant the offset was... off.

To get around this, I modified my formula to allow me to make adjustments to components on the fly:

@function rhythm-offset(
    $target-font-size,
    $line-height-ratio,
    $multiple: 0
) {
    $line-height: $target-font-size * $line-height-ratio;
    $offset: $rhythm-unit - ($line-height % $rhythm-unit);
    @return $offset + 0.125 * $multiple;
}

Instead of adding multiples of the rhythm unit, I decided to use a scale of 0.125rem. I chose this number because it is the smallest perceptible step that could get different elements back on track. From the point of view of a consuming component, I simply needed to provide whatever positive integer got me the closest to the rhythm:

.some-component {  @include get-rhythm($multiple: 4); }

The final result wasn’t 100% perfectly aligned at all viewports for all headline lengths, but I felt that what I had achieved was in the spirit of good vertical rhythm and there wasn’t much more I could do without making serious trade-offs. I’m keeping the visual regression tests around so I can continue to evaluate how the rhythm calculations are working for me.

Should teams adopt vertical rhythm today?

Vertical rhythm just isn’t a subject that gets talked about very often — my searches into the topic didn’t really yield any blog posts written within the last 5 years. What I found did contain a lot of valuable advice on how to compose to a vertical rhythm, and some people even provided examples of how they achieved this in CSS/Sass. So why aren’t more teams doing it?

I totally get that not everyone is a typography nerd, so it might be a tough sell for teams to care about what seems like mundane minutiae — but that doesn’t mean it isn’t valuable work. Here’s why teams should care, at least a little:

  1. As I said before, we want to keep readers engaged: focused on comprehension, making connections, and synthesizing their understanding, and not on the act of reading itself. Vertical rhythm provides structure to the page and guides readers through the content.
  2. When the content changes, it’s rare that teams revisit their CSS code or the design decisions that influenced it. This might be increasing the UX debt of the application and having a real impact on users.
  3. A quality reading experience will be difficult to maintain over time without continued attention on these details, and the time of designers and developers is better spent elsewhere. Teams may not realize how much time they’re currently spending going back and forth on spacing issues around the site, instead of addressing more complex design needs.

Personally, I might not introduce the above Sass into my client projects right away without further testing, but I think it’s worth continuing to explore these ideas. By combining the powers of a CSS framework for typography and automated visual regression testing, we can potentially increase our confidence that we’re delivering an engaging reading experience to our users.