CSS text-wrap: balance, Explained
text-wrap: balance evens out line lengths in headlines using the browser's own layout engine, no JavaScript required. How it works and when to use it.
text-wrap: balance is a CSS value that tells the browser to distribute text across lines as evenly as possible, instead of the default behavior of filling each line greedily until the next word doesn’t fit. It’s built for headlines, pull quotes, and short blocks of text where a lonely last word — an “orphan” — looks unpolished.
The problem it solves
Browsers wrap text with a greedy algorithm: pack words onto a line until the next one overflows, then start a new line. That’s fast and works fine for paragraphs, but it produces ugly results on short text. A three-line headline might render as two long lines and one short trailing word, because the greedy pass never looks ahead.
Designers have worked around this for years with manual <br> tags, non-breaking spaces glued between the last two words, or JavaScript libraries that measure text and re-flow it on every resize. All of those are brittle: manual breaks fall apart at different viewport widths, and JavaScript approaches add a layout thrash on load.
How it works
h1 {
text-wrap: balance;
}
That’s the entire implementation. The browser evaluates a handful of candidate line-break points and picks the arrangement that minimizes the difference between the longest and shortest line, subject to normal wrapping rules like hyphenation and white-space. No JavaScript, no measuring, no reflow on resize — it recalculates automatically whenever the container’s width changes, the same as any other layout property.
Where to use it — and where not to
text-wrap: balance is scoped intentionally. Browsers cap the number of lines it will balance (commonly around four to six, depending on the implementation), because balancing a long paragraph would be expensive to compute on every layout pass and wouldn’t look meaningfully different anyway. That makes it a poor fit for body copy.
Good candidates:
- Headlines and subheadings
- Card titles and short summaries
- Pull quotes
- Button and label text that wraps to two lines
Poor candidates:
- Long-form paragraphs (use
text-wrap: prettyinstead, which improves orphan handling without trying to fully balance every line) - Any element where line count is unpredictable and could exceed the browser’s balancing limit
text-wrap: balance vs text-wrap: pretty
balance | pretty | |
|---|---|---|
| Goal | Even line lengths across the whole block | Avoid a single orphan word on the last line |
| Cost | Higher — evaluates multiple break combinations | Lower — only adjusts the final lines |
| Line limit | Capped (browser-dependent, short blocks only) | No hard cap, safe for paragraphs |
| Best for | Headlines, titles, short labels | Body text, article paragraphs |
Both are values of the same text-wrap property, alongside the default wrap and nowrap. Feature-detect with @supports (text-wrap: balance) if you need a fallback for older browsers — the greedy default is a safe degradation, not a broken one.
Combining it with fluid type
text-wrap: balance composes naturally with responsive typography. If you’re already using clamp() for fluid font sizing, balancing keeps headline line breaks looking intentional across every viewport width the clamp() curve produces, rather than just at the breakpoints you happened to test. It also plays well with container queries — a card title balanced relative to its container re-flows correctly as the card itself resizes, without any extra code.
Because it’s a layout-time calculation handled entirely by the browser’s rendering engine, it has no impact on the critical rendering path beyond what normal text layout already costs. There’s no extra network request and no script to parse, which is a meaningful difference from the JavaScript line-balancing libraries it replaces.
Browser support and fallback strategy
Support has landed in Chromium- and WebKit-based browsers; Firefox support has been rolling out on a similar timeline. Because the property degrades gracefully — unsupported browsers simply keep the default greedy wrap — it’s safe to ship without a polyfill. Wrap it in a feature query if you want to apply a different treatment (like a manually shortened headline) for browsers that don’t support it yet:
@supports (text-wrap: balance) {
.hero-title {
text-wrap: balance;
}
}
The takeaway
text-wrap: balance replaces a class of hacky, JavaScript-driven line-balancing with one CSS declaration. Reach for it on headlines, titles, and other short text blocks where uneven line lengths are visually distracting; reach for text-wrap: pretty instead on body paragraphs, where you just want to avoid a stray last word. Either way, it’s a rendering-engine feature — free of runtime cost and safe to ship with a one-line feature query as your only fallback concern.
Tagged
Keep reading
Takina · · 4 min read CSS object-fit and object-position, Explained
object-fit controls how an image or video is cropped inside its box, and object-position controls which part of it stays visible. How they work together.
Takina · · 5 min read CSS inherit, initial, unset & revert Explained
CSS's four global keywords control where a property's value comes from. How inherit, initial, unset, and revert differ, with a comparison table.
Takina · · 4 min read Dynamic Viewport Units: dvh, svh, and lvh Explained
dvh, svh, and lvh fix the classic mobile vh bug where browser toolbars cut off full-height layouts. Here's what each unit measures and when to use it.