Line length matters more than the font you picked
Everyone argues about typefaces. Almost nobody sets a measure, which is the decision that actually determines whether your writing gets read.
Pick any developer blog at random and there is a decent chance the body text runs the full width of the browser window. On a laptop that is something like 150 characters a line. The type might be beautiful. It will still be exhausting to read.
The reason is mechanical rather than aesthetic. When you finish a line your eye has to travel back and find the start of the next one, and the further it travels the more likely it lands on the wrong line. Do that twice in a paragraph and you stop trusting the page, and shortly after that you stop reading it.
The number
The usual advice is 45 to 75 characters a line, counting spaces, with 66 quoted as the comfortable middle. That figure comes from Robert Bringhurst and it has survived the move from print to screens largely intact.
You do not have to count anything, because CSS has a unit for it. The
ch unit is the width of the 0 glyph in the
current font, which is close enough to an average character:
.prose {
max-width: 66ch;
}
That is the whole technique. It is one property, and it will do more for your readers than any font pairing you agonise over.
ch: it measures the zero glyph,
so in a monospace font 66ch really is 66 characters, while
in a proportional serif it usually lands somewhere between 70 and 80.
Set it, look at it, adjust. Do not treat the unit as exact.
Why the container is the wrong place for it
The common mistake is putting the constraint on a layout wrapper rather than on the text itself:
/* Constrains everything, including things
that want to be wide */
.container {
max-width: 66ch;
}
Now your code samples wrap at 66 characters too, which helps nobody, and your images are the size of a postage stamp. Prose wants a measure. Diagrams, tables and code want room. Those are different requirements and they need different rules.
Set the measure on the flow, then let specific children opt out:
.prose > * {
max-width: 34rem;
}
.prose pre,
.prose figure {
max-width: min(100%, 42rem);
}
Anything the reader consumes a line at a time gets the measure. Anything they scan or study gets the space.
Three things that undo it
- Justified text. Without hyphenation the browser opens rivers of white space to make the edges line up. Left-aligned with a ragged right edge reads better on the web, every time.
- Tight line height. A long line needs more leading, not less. Around 1.6 to 1.75 for body copy, and shorter measures can take a little less.
- Body text under 16 pixels. A generous measure will not rescue type your reader has to lean in for.
Check it, do not guess
Open a console on your own writing and count what you are actually shipping:
const p = document.querySelector('.prose p');
const style = getComputedStyle(p);
const probe = document.createElement('span');
probe.style.cssText = `position:absolute;visibility:hidden;
white-space:nowrap;font:${style.font}`;
probe.textContent = 'abcdefghijklmnopqrstuvwxyz';
document.body.append(probe);
const chWidth = probe.getBoundingClientRect().width / 26;
console.log(Math.round(p.clientWidth / chWidth), 'characters');
probe.remove();
Anything from the mid sixties to the mid seventies is fine. If it prints 120, you have found the thing to fix before you touch the typeface.
None of this is new. It is just quietly ignored, because choosing a font feels like design and setting a maximum width feels like plumbing. The plumbing is what people notice, though, and they notice it by staying.
This post is demo content for Standard Output, a free blog template. Replace it with your own.