text-wrap: balance for balanced headlines with no JS
Published March 26, 2027
h1, h2, .card-title {
text-wrap: balance;
max-width: 40ch;
}
blockquote {
text-wrap: balance;
max-width: 60ch;
}What
text-wrap: balance tells the browser to distribute a block's text evenly across its wrapped lines, instead of the default greedy algorithm that fills each line as full as possible before wrapping the leftover — the fix for a heading that wraps to one lonely word on its last line.
Why it matters
Default line-breaking is greedy: pack line one full, wrap whatever's left to line two, repeat. That frequently produces an ugly ratio — nine words on line one, one word alone on line two — and it's worse the shorter the text is, which is exactly the case for headlines, card titles, and pull quotes. The manual fixes have always been unsatisfying: hard-coded <br> tags that look right at one viewport width and wrong at every other, or a JS library that measures rendered text width and re-inserts breaks on every resize. text-wrap: balance computes the balanced distribution inside the layout engine itself, using the same line-breaking logic that's already running, and it re-balances automatically on every reflow — resize the window and it just stays balanced, for free.
How it works
The snippet applies text-wrap: balance to headings and blockquotes, paired with a max-width so there's actually more than one line to balance across:
- The browser tries narrower maximum line-widths within the box and picks the narrowest one that still renders the content in the same number of lines the greedy algorithm would have used — it redistributes within the existing line count, it doesn't add an extra line to make things look neater.
max-width: 40chisn't required by the property, but balancing has no effect on a heading that already fits on one line — give it room to wrap onto two or more lines somewhere in your breakpoints for the effect to be visible at all.
Gotchas
- Chromium caps balancing at 6 lines, Firefox at 10 — past that, it silently falls back to normal greedy wrapping. Computing a balanced layout is expensive (roughly quadratic in line count), so this is a deliberate spec-permitted limit, not a bug. Reach for
balanceon headlines/captions/short blurbs by design, not on paragraph body text. text-wrapis a shorthand. The actual logic lives on the longhandtext-wrap-style(plus a separatetext-wrap-modefor the wrap/no-wrap axis).text-wrap: balanceis equivalent totext-wrap-style: balanceand is what most code in the wild uses — the split just exists for cases where you needtext-wrap-modeandtext-wrap-styleset independently, which the shorthand can't express.- No feature-detection needed. An unsupported browser just ignores the value and wraps text with the normal greedy algorithm — nothing breaks, it just isn't balanced.
Browser support: Baseline 2024 — Chrome 114+, Firefox 121+, Safari 17.5+. Safe to ship with zero fallback.
Related
text-wrap: pretty— a slower, more thorough algorithm aimed at avoiding orphans and improving overall typography, with narrower browser support thanbalance; a different heuristic for a similar goal.hyphens: auto— operates on a different axis (breaking within long words), and composes withtext-wrap: balancerather than replacing it.