
How to Use the CSS text-wrap: balance and pretty Properties?
- Sajjad
- Typography
- 01 Oct, 2026
You write a hero headline that fits perfectly on your laptop, then open the page on a phone and watch it break into three lines with a single word stranded on the last one. On a different screen width, the first line runs the full width of the container and the second line holds two short words. For years the fixes were manual: a <br> in the CMS, a non-breaking space between the last two words, or a JavaScript library that measured text and adjusted it. None of those survive a responsive layout or a copy edit.
CSS now handles this natively. text-wrap: balance distributes text evenly across lines, and text-wrap: pretty improves how paragraphs end. This article explains how each value works, where to use them, how browsers implement them differently, and the limits you should know before you apply them globally.
What Is text-wrap?
text-wrap is a CSS property that controls how the browser breaks lines of text. In the CSS Text Module Level 4, it is a shorthand for two longhands:
text-wrap-modedecides whether text wraps at all:wrapornowrap.text-wrap-styledecides how wrapped text chooses its break points:auto,balance,pretty, orstable.
So when you write text-wrap: balance, you are setting text-wrap-mode: wrap and text-wrap-style: balance together. Here is what each style value does:
| Value | What it does | Best for |
|---|---|---|
auto | The default. Fills each line greedily, one line at a time | Everything, unless you need more |
balance | Makes all lines roughly the same length | Headings, captions, short quotes |
pretty | Uses a slower algorithm to avoid very short last lines and improve the rag | Body paragraphs |
stable | Avoids reflowing earlier lines when content after them changes | Editable text, live input |
Why the Default Algorithm Produces Awkward Breaks
Browsers have traditionally used a greedy line-breaking algorithm. It places as many words as will fit on line one, moves to line two, and repeats. It never looks back. That is fast and predictable, but it optimizes each line in isolation, so it cannot notice that the final line ends up holding a single word, or that a two-line headline would look better split 50/50 than 90/10.
Typesetting systems like TeX use a paragraph-wide algorithm (Knuth–Plass) that considers every possible set of breaks and picks the one with the lowest total "badness." That produces much more even text but costs more computation. balance and pretty bring a version of that thinking to the browser, scoped so it stays fast.
How text-wrap: balance Works
With balance, the browser first works out how many lines the text needs at the current width. Then it searches for the narrowest line length that still fits the text in that same number of lines. The result is a block where every line is about the same width.
h1,
h2,
h3,
blockquote,
figcaption {
text-wrap: balance;
}
Before and after for a two-line heading at a narrow width:
| Default wrapping | Balanced wrapping |
|---|---|
| Line 1: "How to Use the CSS text-wrap: balance and" | Line 1: "How to Use the CSS text-wrap:" |
| Line 2: "pretty Properties" | Line 2: "balance and pretty Properties" |
The number of lines never changes. Balancing only redistributes words across the lines the text already needed.
Line Limits
Balancing is more expensive than greedy wrapping, so browsers cap it. Chromium balances text up to six lines and Firefox up to ten. Beyond the limit, the browser silently falls back to normal wrapping. This is deliberate: balance is meant for short text, and on a long paragraph a perfectly even block looks unnatural anyway.
The Box Does Not Shrink
A balanced heading has shorter lines, but its element is still as wide as its container. If you put a background, border, or underline on the heading itself, you will see empty space on the right.
/* The background spans the full width, not the balanced text */
.tag-heading {
text-wrap: balance;
background: var(--color-accent-soft);
}
/* Shrink the box to the text when you need a tight background */
.tag-heading {
text-wrap: balance;
width: fit-content;
max-width: 100%;
}
For centered headings this rarely matters, because the text sits in the middle either way. For left-aligned headings with decorations, add width: fit-content or move the decoration to an inline element.
How text-wrap: pretty Works
pretty is aimed at paragraphs. It tells the browser to favour typographic quality over speed when choosing breaks. The specification leaves the exact algorithm to each browser, and the engines have taken different approaches:
- Chromium (Chrome, Edge, Opera) focuses on the end of the paragraph. It examines the last four lines and adjusts breaks to avoid a single-word final line, which typographers call a runt and many people loosely call an orphan.
- Safari applies a fuller paragraph-wide evaluation. It improves the overall rag (the ragged right edge), reduces bad hyphenation, and avoids short last lines across the whole paragraph, not just the ending.
- Firefox has been slower to ship
pretty. Where it is unsupported, the value is ignored and text wraps normally.
p,
li,
dd {
text-wrap: pretty;
}
Because unsupported browsers just use the default, pretty is a safe progressive enhancement. Nobody gets a broken layout, and some readers get noticeably better paragraphs.
For a broader look at controlling short last lines and lines stranded across columns or pages, see the article on how to prevent orphans and widows.
balance vs. pretty: When to Use Each
| Question | balance | pretty |
|---|---|---|
| What does it optimize? | Equal line lengths | A good last line and a smoother rag |
| How many lines does it handle? | Capped (6 in Chromium, 10 in Firefox) | Any length |
| Does it change the number of lines? | No | Occasionally, by pulling a word down |
| Typical targets | Headings, card titles, captions | Paragraphs, list items, descriptions |
| Cost | Moderate, limited by line cap | Higher per paragraph, still small |
A good default is: balance for anything that is meant to be read at a glance, pretty for anything that is meant to be read line by line. Do not apply balance to body copy. Evenly balanced paragraphs often end up with every line shorter than the measure, which wastes space and makes the text column look narrower than you designed it. If you are tuning the measure itself, the post on the ideal line length for web content covers the 45–75 character range.
A Sensible Global Setup
Most sites can add these few lines to their base stylesheet and forget about them:
@layer base {
h1,
h2,
h3,
h4,
h5,
h6,
blockquote,
figcaption,
.card-title {
text-wrap: balance;
}
p,
li,
dt,
dd {
text-wrap: pretty;
}
}
If your component styles live in a higher cascade layer, they can still override this with text-wrap: wrap where needed.
In Tailwind CSS v4
Tailwind v4 ships utilities for every value: text-wrap, text-nowrap, text-balance, and text-pretty. To apply them globally, add base styles in your CSS entry file:
@import "tailwindcss";
@layer base {
h1,
h2,
h3 {
@apply text-balance;
}
p {
@apply text-pretty;
}
}
Or use the utilities directly in markup:
export function Hero() {
return (
<section className="mx-auto max-w-3xl text-center">
<h1 className="text-5xl font-bold text-balance">
Ship faster websites without sacrificing typography
</h1>
<p className="mt-6 text-lg text-pretty">
A practical guide to fonts, spacing, and layout for teams that care about the details.
</p>
</section>
);
}
What About text-wrap: stable?
stable solves a different problem. In a contenteditable region or a textarea, a paragraph-wide algorithm could rewrap lines above the cursor every time you type, which makes text jump around while you edit. stable tells the browser that, when content changes, lines before the edit point should not move.
[contenteditable],
textarea {
text-wrap: stable;
}
Use it for rich text editors, comment boxes, and anywhere text updates live. Do not combine pretty with editable fields.
Interactions with Other Typography Properties
Hyphenation
hyphens: auto gives the line breaker more options, which helps both balance and pretty find better solutions. Safari in particular uses hyphenation decisions as part of its pretty scoring. For language setup and fine control, read how to control hyphenation with CSS.
Text Alignment
Both values work with text-align: left, center, and right. Balanced, centered headings look especially good, which is why hero sections benefit most. Avoid pairing either value with text-align: justify; justification has its own spacing problems on the web.
Non-Breaking Spaces
You no longer need a between the last two words of a heading to avoid a runt, and leftover manual non-breaking spaces can now fight the balancing algorithm. When you adopt balance, it is worth searching your CMS content for hard-coded and <br> tags in headings and removing them.
Fluid Type
If headline sizes use clamp(), the number of lines changes as the viewport changes, and balance re-evaluates each time. That is exactly the scenario it was designed for. See fluid typography with CSS clamp() for the sizing side.
Performance Considerations
The cost of balance and pretty is paid during layout. For a page with dozens of headings and a few hundred paragraphs, the difference is negligible on modern devices. Problems only appear in extreme cases:
- Huge lists of balanced items. Thousands of balanced card titles in an infinite-scroll feed add up. Measure with the Performance panel before and after.
- Very long paragraphs with pretty. Chromium only adjusts the end of the paragraph, so its cost stays bounded. Engines with fuller algorithms do more work, but browsers include their own safeguards.
- Frequent re-layout. Text that resizes on every animation frame (for example, animated container widths) re-runs the algorithm each frame. Turn the value off for elements that animate their width.
As a rule, apply balance by element type rather than with a universal selector, and you will never notice the cost.
Testing and Debugging
- Resize slowly. Drag the viewport width in DevTools' responsive mode and watch headings re-balance. You should never see a single-word last line on a balanced heading.
- Check the computed value. In the Computed panel, look for
text-wrap-style. If it showsauto, something later in the cascade reset it. - Test in more than one engine. Because
prettydiffers between Chromium and Safari, the same paragraph can end differently. That is expected, not a bug. - Use feature queries when you need a fallback. If you rely on balancing for a specific design, you can provide an alternative:
.hero-title {
max-width: 18ch;
}
@supports (text-wrap: balance) {
.hero-title {
max-width: none;
text-wrap: balance;
}
}
text-wrap FAQ
Balance is supported in current versions of Chrome, Edge, Firefox, and Safari, and has been for several release cycles. Older browsers simply ignore the value and wrap text normally, so it is safe to use without a fallback in most designs.
Browsers only balance short blocks of text. Chromium stops at six lines and Firefox at ten, and anything longer falls back to normal wrapping. Use pretty for paragraphs instead, and reserve balance for headings, captions, and other short text.
Partly. In Chromium, pretty mainly prevents a single short word from sitting alone on the last line of a paragraph. Safari goes further and improves the rag of the whole paragraph. Neither controls widows and orphans across columns or printed pages, which are handled by the separate widows and orphans properties.
You can, but you should not. Balancing body paragraphs makes every line shorter than your intended measure, and the line cap means long text gets no benefit anyway. Apply balance to headings and short display text, and pretty to running text.
No. It only changes where visual line breaks fall. The text content, its order, and the accessibility tree are unchanged, so search engines and assistive technology read exactly the same words.
For modern browsers, no. The native property is faster, reacts to resizing automatically, and does not cause a flash of re-wrapping after scripts load. You can safely remove older balancing libraries once your audience is on current browsers.
Conclusion
text-wrap: balance and text-wrap: pretty fix two problems that used to require manual line breaks or JavaScript: lopsided headlines and paragraphs that end with a lonely word. Both are one-line declarations, both degrade gracefully, and both adapt automatically as your layout changes width.
Treat them as part of your base stylesheet. Balance headings, captions, and card titles; make paragraphs and list items pretty; use stable for editable text. Then clean out the hard-coded line breaks and non-breaking spaces your content team added over the years, because the browser can now do that job better than they could.
Here are some useful references for going deeper on text-wrap:
- MDN Web Docs: text-wrap — values, longhands, and browser compatibility.
- Chrome for Developers: CSS text-wrap: balance — how Chromium implements balancing and its line limit.
- Chrome for Developers: CSS text-wrap: pretty — the Chromium approach to avoiding short last lines.
- W3C: CSS Text Module Level 4 — the specification for text-wrap-mode and text-wrap-style.


