← blog
CSSJuly 28, 2026 · 4 min read

You hand-edit headlines to avoid orphaned words. text-wrap: balance does it natively.

The classic fix for a headline that breaks awkwardly — a manual `<br>`, a `&shy;`, or a max-width tweak — exists because CSS had no way to distribute line breaks evenly. `text-wrap: balance` and `text-wrap: pretty` are the native answers.

Parsa Jiravand · Frontend engineer · building bestpractic
You hand-edit headlines to avoid orphaned words. `text-wrap: balance` does it natively.

Here is a small but persistent annoyance in frontend work:

HTML
1
2
<h1>The Practical Guide to Building Resilient Web</h1>

The browser broke the headline at "Web" because it ran out of space. Now you have one word sitting alone on the second line. You fix it by shortening a word, tweaking max-width, or inserting a <br> that will be wrong at a different viewport width anyway.

This is not a rare edge case. It happens every time a heading is near the container edge, and every fix that works at one width breaks at another.

text-wrap: balance is the native solution.

text-wrap: balance tells the browser to distribute the text as evenly as possible across all lines, rather than filling each line greedily until it overflows. The browser picks the break points; you don't guess.

CSS
1
2
3
h1, h2, h3 { text-wrap: balance; }

Before, with the default greedy wrapping:

Text
1
2
The Practical Guide to Building Resilient Web

After, with text-wrap: balance:

Text
1
2
The Practical Guide to Building Resilient Web

Both lines are closer to equal in length. The orphan disappears. No <br>, no max-width in ch units, no viewport-specific overrides.

The property is limited to short content — the browser caps the lookahead at around six lines. That is intentional: the algorithm is quadratic, and running it on a 500-word block would be expensive. Headlines and pull quotes are exactly the right target.

Runs right in your browser — poke at it and watch the concept react live.

Long-form paragraphs have their own orphan problem: a single word stranded at the start of the last line. text-wrap: balance is too aggressive for running text — balancing a 10-line paragraph would shift nearly every line. text-wrap: pretty is the calibrated version.

CSS
1
2
3
p, li, blockquote { text-wrap: pretty; }

pretty uses a lookahead only on the last few lines of a block, pulling one word back if it would otherwise sit alone. The result looks identical to balance for the last line, but the rest of the paragraph is untouched.

CSS
1
2
3
4
5
6
7
8
/* Recommended defaults */ h1, h2, h3, h4, h5, h6 { text-wrap: balance; } p, li, figcaption, blockquote { text-wrap: pretty; }

This pair covers both problems with two rules and no JavaScript.

<br> tags. Work at one width. Wrong at every other width. Require you to re-edit content when the container changes.

&shy; soft hyphens. Depend on hyphenation, which is language-sensitive and not always what you want for brand names or technical terms.

max-width tweaks. Force the heading into a narrower box to avoid the bad break. Move the break to a different width. Still wrong somewhere.

JavaScript rebalancing (e.g. react-text-balancer). Measures the element after render and inserts zero-width spaces or spans to approximate balance. Requires a ResizeObserver, adds DOM complexity, and causes a repaint.

text-wrap: balance does none of this. The browser solves the line-breaking problem during layout, before anything is painted. There is no DOM surgery, no observer, no flash of unbalanced content.

A marketing page card with a headline and a description:

HTML
1
2
3
4
5
6
7
<article class="card"> <h2>Automate Your Deployment Pipeline Without the Overhead</h2> <p> Learn how to wire up a zero-downtime deploy in an afternoon using tools your team already has installed. </p> </article>
CSS
1
2
3
4
5
6
7
8
.card h2 { text-wrap: balance; font-size: clamp(1.25rem, 2.5vw, 1.75rem); } .card p { text-wrap: pretty; }

The h2 distributes across lines evenly regardless of the card's width — useful in a grid where card widths vary by column count. The p avoids a trailing orphan without disrupting the rhythm of the rest of the paragraph. Both properties do their jobs silently while the layout shifts.

text-wrap: balance is Baseline 2024: Chrome 114 (June 2023), Firefox 121 (December 2023), Safari 17.4 (March 2024).

text-wrap: pretty shipped slightly later: Chrome 117, Firefox 128, Safari 17.4.

Both degrade gracefully — unsupported browsers use the default greedy wrapping. The text is still readable; it just may have an orphan. That is the correct fallback behavior for a visual refinement.

There is no polyfill needed and nothing to install.

Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.

Search your stylesheets for <br> tags inside headings, or for max-width values expressed in ch units that exist specifically to force a nicer headline break. Each one is a layout constraint solving a problem CSS can now handle natively.

Add text-wrap: balance to your heading selectors and text-wrap: pretty to your body text selectors. The browser finds the right breaks at every viewport width, for every heading length, without any JavaScript or content edits on your part.


🚀 Want more like this? Every guide, playground, and quiz lives on bestpractic.org — open it and sign up free so the next one finds you.

Thanks for reading! Let's stay connected:

Keep reading

One post a day, in your inbox

Each one with a runnable playground and a quiz. No pitch, no digest, unsubscribe in one click.

0 comments

Sign in to join the discussion, like comments, and save articles for later.