Articles

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.

Takina Takina · · 4 min read
Close-up of CSS code on a screen

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: pretty instead, 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

balancepretty
GoalEven line lengths across the whole blockAvoid a single orphan word on the last line
CostHigher — evaluates multiple break combinationsLower — only adjusts the final lines
Line limitCapped (browser-dependent, short blocks only)No hard cap, safe for paragraphs
Best forHeadlines, titles, short labelsBody 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.

Takina 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.

#CSS #Web Development #Frontend
Takina 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.

#CSS #Web Development #Frontend
Takina 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.

#CSS #Web Development #Frontend