Intro
CSS text-wrap: balance | CSS and UI | Chrome for Developers
A classic typography technique of hand-authoring line breaks for balanced text blocks, comes to CSS.
https://developer.chrome.com/docs/css-ui/css-text-wrap-balance?hl=enYou may not have heard of text-wrap: balance yet, but as you can see from the Google documentation above, it is a CSS property belonging to CSS Text Level 4, supported since Chrome 114.
Let’s first take a look at what this feature does.
What is text-wrap: balance?
See the Pen Animated comparison of balanced and unbalanced headlines by web.dev (@web-dot-dev) on CodePen.
Source: https://developer.chrome.com/docs/css-ui/css-text-wrap-balanceAs of March 2024, this should render properly if you are not on Safari and are using Chrome 114 or above.
Based on what we have seen so far — the meaning of the word and the example — you can probably guess that text-wrap: balance is a feature that balances text line breaks.
But there is something that feels a bit off.
Unlike other clearly defined properties, the word “balance” feels somewhat vague in the context of communicating with a computer.
The Chrome page’s introduction also describes it only as follows:
you can request the browser to figure out the best balanced line wrapping solution for the text
I became curious about what criteria are used to achieve this “balance.”
Before diving deep, let’s warm up by looking at the specification and origins of this feature.
Let’s examine the text-wrapping specification on the W3C working group.
https://www.w3.org/TR/css-text-4/#text-wrapping
Let’s highlight the important parts:
Aha! So there is a fairly concrete decision-making mechanism described here.
The line breaks are determined so that the remaining space in each line approaches the average. In simpler terms, when deciding where to break lines, the goal is to make the remaining space in each line roughly equal.
Before going deeper, there is one more question remaining.
Where did this feature come from?
Origins
Well, it is not exactly something with ancient roots, but…
Previously, people manually controlled line breaks using <wbr> tags or ­ for readability.
Or they used JavaScript libraries to handle line breaking.
https://open.nytimes.com/headline-balancing-act-6e92d3d6119
No description available
https://open.nytimes.com/headline-balancing-act-6e92d3d6119According to the New York Times, this feature was used to balance newspaper headlines. (Related JS code: https://github.com/nytimes/text-balancer)\ Other examples include https://github.com/adobe/balance-text and https://github.com/shuding/react-wrap-balancer.
On the Android side, this was already implemented in some areas. (https://cs.android.com/android/platform/superproject/+/master:frameworks/minikin/include/minikin/LineBreaker.h;l=38;drc=5ca657189aac546af0aafaba11bbc9c5d889eab3?hl=ja)
Overall, this can be seen as a feature that has been used for text readability in advertisements, newspapers, web pages, and more.
The Dive
Now that we have a rough idea of what this feature is and where it came from, you are free to turn back.
From here on, we will trace this feature from start to finish.
Let’s start by looking at the related documentation.
blink-dev Group Email
Intent to Ship: CSS headline balancing
This is an email posted by ‘Koji Ishii’ to the blink-dev group. A lengthy discussion follows below. Let’s start by looking at Koji’s email.
Specification
https://w3c.github.io/csswg-drafts/css-text-4/#valdef-text-wrap-balance\ This is the specification posted on csswg-drafts.
Design doc
https://docs.google.com/document/d/16-T9gqCagJxcST6hcnneSb7qGunxXa37_UHYqMqhPL0/edit?usp=sharing This is the design document written by ‘Koji Ishii’. It is not very long and mainly focuses on the implementation. We will look at it later; for now, let’s continue with the email.
TAG review
https://github.com/w3ctag/design-reviews/issues/822
Here, TAG stands for Technical Architecture Group, a group that reviews technical issues at W3C.
The review of text-wrap: balance was conducted through this issue.
The basic content is the same as the specification and design documents we looked at earlier, and the links are the same as well.
Additionally, there is content about testing.
Testing is done on wpt.fyi (Web Platform Tests Dashboard), managed by W3C. WPT stands for Web Platform Tests, a test suite for testing web platform standards.
Each test case is split into HTML files, structured like this:
<!DOCTYPE html>
<link rel="help" href="https://drafts.csswg.org/css-text-4/#valdef-text-wrap-balance">
<link rel="match" href="reference/text-wrap-balance-overflow-001-ref.html">
<style>
.container {
font-family: monospace;
font-size: 20px;
inline-size: 15ch;
border: 1px solid;
overflow-wrap: break-word;
text-wrap: balance;
}
</style>
<div class="container">CONTROLLING YOUR BU</div>
<div class="container">CONTROLLING YOUR BU BU</div>
You can also check them live, of course.
https://wpt.live/css/css-text/white-space/text-wrap-balance-overflow-001.html
Related PR: https://github.com/web-platform-tests/interop/issues/561
It feels like we have taken quite a detour, so let’s get back to the email.
Interoperability and Compatibility
The topic of interoperability and compatibility comes up. Naturally, compatibility with other browsers is important for the ecosystem. Koji has attached issues where he requested each browser project’s position on this feature. These are not issues on the actual engine projects, but rather position requests made through standards-positions issues.
Mozilla (https://github.com/mozilla/standards-positions/issues/755)
The issues and PRs that Mozilla wrote after reviewing the specification can be found here:
- Standards position issue (https://bugzilla.mozilla.org/show_bug.cgi?id=1731541)
- One of the related PRs (https://phabricator.services.mozilla.com/D187543)
WebKit (https://github.com/WebKit/standards-positions/issues/143)
Apple’s WebKit side is tracking bugs here: https://bugs.webkit.org/show_bug.cgi?id=249840
The related PR can be found here.\
Provide an initial implementation of `text-wrap: balance` by RWDavid · Pull Request #16723 · WebKit/WebKit
2d299a2 Provide an initial implementation of `text-wrap: balance` https://bugs.webkit.org/show_bug.cgi?id=249840 rdar://problem/103663513 Reviewed by Alan Baradlay. This patch implements `text-wr...
https://github.com/WebKit/WebKit/pull/16723In Apple’s case, you can check build results for each environment (by OS) before merging through EWS (Early Warning System).
This is beyond the scope of this post, so feel free to explore on your own.
EWS link (https://ews-build.webkit.org/#/builders/26/builds/15587)
EWS (https://github.com/webkit-early-warning-system)
Let’s recap where we are.
Through Koji’s email, we examined the feature’s specification, design document, TAG review, tests, and cross-browser compatibility issues. We also looked at the issues and PRs where each browser’s position on the feature was requested.
The email itself is covered well enough at this point… Let’s look at the discussion among the blink-dev group members who received this email.
Actually, I was going to do that, but the content is quite long, and I am not sure it is necessary to go through all of it.
The discussion mainly covered performance concerns, relationships with other properties (white-space), clarity of implementation, and control over the feature (such as whether the last line’s length should be 4em or at least 15% of the total line), among other topics.
Let’s just summarize the major issues that were discussed.
In the case of text-wrap, which controls line wrapping, it conflicts with the existing white-space property. As a result, there was a need to reconcile the two.
The white-space property controls whitespace handling and line-breaking behavior, but when using values like text-wrap: balance, additional behavior for balancing line breaks is required.
The proposed solution was to make white-space encompass the values of text-wrap as well, effectively making it function as a shorthand.
A similar precedent existed with baseline-source, which also had a conflict with vertical-align. The solution proposed was to allow baseline-source to be used as a value of vertical-align. [baseline-source] Set baseline-source to auto when vertical-align set.
Let’s Pause Here…
Going through all of this, I could see just how many steps a single feature goes through before it lands in a browser.
But our original journey was about the specification and implementation of text-wrap: balance.
Since we have come this far just looking at the related specifications and work, I have run out of energy to cover the implementation as well.
It seems that reading through specifications led me into the swamp of countless hyperlinks.
Still, I hope this serves as a signpost for those who are curious about where each engine’s issues and PRs are managed, and where tests are conducted.
So I will wrap up this post here, and in the next post, we will look at the actual implementation. (I have already done the research. No need to worry.)
Until next time.