Articles

Knuth–Plass: line breaking for books

Why browsers break lines one at a time, why TeX optimizes the whole paragraph, and how Palatine brings that to HTML.

By Palatine · Published · Updated

A justified paragraph has one degree of freedom: the space between words. Every line must reach the same right edge, so whatever the words leave over is spread across the spaces of that line. The question is where to break the lines so that no line has to stretch much.

One line at a time

Browsers, word processors and most HTML-to-PDF tools answer it greedily: put as many words on the line as fit, break, and continue. It is fast and never looks back. But a decision on line three can force a terrible line five, and greedy breaking cannot see it coming. The result is the familiar look of justified web text: some lines tight, some full of holes, and vertical "rivers" of white running through the paragraph.

The whole paragraph at once

In 1981 Donald Knuth and Michael Plass published the algorithm TeX still uses. It models the paragraph as boxes (words), glue (spaces that can stretch and shrink) and penalties (places where a break is possible but costly, like a hyphen), then finds the set of breaks that minimizes the total "badness" of all lines together. A line that stretches a little is cheap; a line that stretches a lot is very expensive; two hyphens in a row, or a very loose line next to a very tight one, cost extra. Dynamic programming keeps it fast: each break point only needs the best way to reach it.

The same text, the same measure, broken both ways:

THE SPACE BETWEEN THE WORDS
A line at a time.Browser-style line breaking

Typesetting a book is mostly a matter of patience. Every line of a justified paragraph has to be filled to the same measure, and the space between words is the only thing the compositor can stretch. Break the lines one at a time and a long word at the wrong moment leaves a line full of holes.

Same words. Same width. Different line breaks. An illustration of paragraph-wide composition.

The line-by-line version fills each line as much as it can and pays for it further down. The total-fit version may squeeze a line slightly or leave a word for the next one, so that no line has to stretch much. Switch between Before and After to watch the words move into a more balanced paragraph. Both layouts are computed in your browser, with this page's font; this simplified illustration does not run the full Palatine composer. On a real page, with hyphenation, the difference compounds over hundreds of paragraphs: it is what makes a book look typeset.

In Palatine

Palatine has a Knuth–Plass composer in its C++ layout engine. It works on the real shaped text — HarfBuzz glyph advances, kerning, ligatures, your fonts — and keeps inline styles and links intact, so a bold word or a link in the middle of a paragraph is broken like any other. It is an explicit option, per render:

const pdf = await renderer.render({
  html, css, format: "pdf",
  options: { typography: { justification: { algorithm: "knuth-plass" } } }
});

With the native CLI, it is --knuth-plass. Around the composer, the same option object controls:

  • Word spacing: the minimum, normal and maximum width of a space, as factors of the font's own space.
  • Hyphenation: soft hyphens in any language, hyphens: auto for English, and penalties so that consecutive hyphenated lines are rare.
  • Last line: a minimum fill for the last line of a paragraph, to avoid a lone short word.
  • Optical margin alignment: quotes, brackets and punctuation hang slightly outside the measure, so the edge of the text looks straight to the eye.

Combined with paged media — widows and orphans, footnotes, running headers — this is what Palatine is built for: books, magazines, long reports, any document that is mostly text and will be read on paper or as a PDF.

Limits

The composer handles horizontal, left-to-right justified paragraphs. Paragraphs it does not handle — right-to-left or vertical text, inline floats — fall back to the line-by-line breaker rather than losing content. Text that is not justified keeps its ragged edge. Greedy remains the default, so turning Knuth–Plass on never changes a document by surprise.


All articles