The Trouble With Unitless Line-Heights How to (efficiently) declare lots of line-heights in CSS for multiple target layouts

Summary: Line-heights are tricky in responsive web design. It’s easy enough to set font sizes that adapt well to different size layouts, but line-heights can only be conveniently declared proportionate to the parent font — and that leads to some bland typography that can only be fixed with a lot of thoughtful re-declaring of line-heights … for every selector, in every layout. This article explains the problem and my solution for my high-traffic, successful website, PainScience.com, which has several complex style sheets for many different layout contexts (i.e. web, small and large, print, PDF, and more).

Font-sizes are nice and easy to change relative to a base font size. You can set a base font size of 20pt, and then all elements defined as 1.1em will automagically be 22pt — tidy. If you change the base font size (for smaller windows, say), all those 1.1em elements will still be 10% larger than the base font — so there’s nothing else to do.

Describing line-heights with CSS is much less tidy.

Line-height can only be declared relative to the size of the parent font — so a bigger font means a bigger line height, every time. That’s not really what a typesetter wants, but it is effectively the only option (because the other ways of declaring line-height are so awkward that they are really rather useless for complex typography).

So it’s a common practice in web typography, if line-height is considered at all, to set a unitless value for line-height, say 1.5 — rather than 15pt or 1.5em or 150%, all of which are just asking for even more trouble. The purity of the unitless multiplier seems pretty sexy at first. Set 1.5 for the page, and by golly everything on the page inherits it: all line-heights end up 1.5 times larger than the font size, whatever it may be.

Unitless line-heights were, I think, popularized by Eric Meyer:

The property line-height can accept unitless number values. You can also give line-height united values, though generally you shouldn’t. But unitless numbers are just fine for this property.

“Just fine” meaning “won’t break your layout.” Fine if your design doesn’t have to adapt to different window sizes. Fine if you want a C+ in web typography 101. If you want an A, you’ll have to dig a little deeper.

Alas, unitless line-heights are more convenient than useful. They make it easy to make non-horrible line-heights. Without tweaking a bunch of elements, it will cause an annoying uninformity of text density, and rob the layout of a key visual clue that differentiates text with different purposes. For instance, I usually want a sidebar to look denser and “darker” than the body text: a line height that is only 1.3 times the font size, perhaps, not 1.5. It needs to be smaller and tighter, and the 1.5 multipler just doesn’t cinch up the leading enough.

(While researching this article, I came across some moron explaining how good typography requires sidebar lines to be precisely aligned with body text lines. Oh my.)

Generally, line-height needs to change more than font-size. For instance, a 10% reduction in font size may look best not with a proportionate 10% reduction in line-height, but 20%. Example:

0.8em text: 20% smaller than the body, with a line height of 1.5. Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

That’s not bad, but maybe it’s a little loose. Here it is a little blacker, which I prefer for blockquotes:

0.8em text: 20% smaller than the body, with a line height of 1.3. Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Nor is just a matter of setting line-heights to change a little more than font-size but in the same direction. If it was, you could just go through a stylesheet and dumbly change every line-height declaration according to a simple formula. But line-heights and font-sizes may even go in opposite directions! For instance, imagine the ridiculously excessive line-height you’d get by multiplying 36pt type by 1.5: do you really want a 54-point line-height, ever? Not in most layouts! Large title type typically needs relatively much less vertical space than body text.

The point is that only an amateur typographer thinks it’s a good thing to set a base line-height with one unitless value and then walk away. Line-height really needs to be set thoughtfully for each element: there is no relativity shortcut, like there is with font-size.

But how is that different than font-size? I already declare a new font-size for every element what needs it — dozens of them! The difference is that most of those font-sizes do not have to be adjusted for different layouts (for different display sizes and contexts). You can set ‘em and forget ‘em. Just change the base font size for each layout, and all the other font sizes adjust accordingly.

But with radically different window and page sizes, line-heights do have to be reconsidered and restated. That 1.3 line-height multiplier that looked great in sidebars in a big window? It’s way too much on an iPhone! The font-size of .9em set in the main stylesheet still works, but the 1.3 has to be changed. Fine tuning many line-height declarations gets hairy with one layout — more than three is just insane. I have stylesheets for three different window sizes, for print, and a range of PDFs.

My solution was to start declaring line-heights in large batches for all common relative heights, so that they can be efficiently re-declared in batches. All the elements and classes that need to be tighter or a lot tighter are listed in one place, and given a line-height of 1.4 or 1.2 all at once. I also give the line-height an arbitrary class name, so that I can assign that line-height where I want it. So for a large layout, my “loose” line height might be 1.5, and is applied to a bunch of elements:

.loose, item1, item2, item3 … {line-height:1.5}

But then for a small screen, “loose” isn’t as loose!

.loose, item1, item2, item3 … {line-height:1.2}

Without this method, I would have dozens of independent line-height declarations, all of which would have to be changed one at a time if I changed my base font size. Yikes. So this makes maintenance of complex web typography much simpler. If anything about this can be “simple”!