ヨンソクのブログ
戻る
4 min read
text-wrap balanceのルーツを辿る [1]

イントロ

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=en

text-wrap: balance まだ聞いたことがない人もいるかもしれないが、 上記のGoogle文書で確認できるように、Chrome 114から対応されたCSS Text Level4に属するCSSプロパティだ。

どんな機能なのか、まず見てみよう。

text-wrap: balance とは?

See the Pen Animated comparison of balanced and unbalanced headlines by web.dev (@web-dot-dev) on CodePen.

出典: https://developer.chrome.com/docs/css-ui/css-text-wrap-balance

2024年3月時点で、Safariでなく、Chrome 114以上であれば正しく表示されるはずだ。 ここまで見た段階では、言葉の意味とサンプルを参考にすると、text-wrap: balanceはテキストの改行をバランスよく調整してくれる機能だと予想できるだろう。

ところが、何か違和感を覚える部分がある。

他の明確なプロパティとは異なり、「バランス」という言葉がコンピュータとのコミュニケーションにおいては不思議に感じられる。

Chromeページの紹介文も以下のようにしか説明されていない。

you can request the browser to figure out the best balanced line wrapping solution for the text

どんな基準でバランスを取っているのか、それが気になった。

ダイビング前の準備体操として、この機能の仕様と起源について調べてみよう。

W3C WGに書かれているtext-wrappingの仕様を見てみよう。
https://www.w3.org/TR/css-text-4/#text-wrapping

重要な部分を見てみると以下の通りだ。

なるほど!ある程度具体的な決定方法が説明されている。
残りスペースのサイズが平均に近づくように改行を決定するということだ。簡単に言えば、改行を決定する際に、改行後の残りスペースのサイズが似通うようにするということだ。

では、より深く掘り下げる前に、残った疑問がある。
この機能はどこから生まれたのだろうか?

起源

とは言っても、そこまで深い根源があるわけではないが…

以前はリーダビリティのために<wbr>タグや&shy;を使って手動で改行を調整していた。
あるいはJavaScriptで改行を調整するライブラリを使用していた。

https://open.nytimes.com/headline-balancing-act-6e92d3d6119

No description available

https://open.nytimes.com/headline-balancing-act-6e92d3d6119

ニューヨーク・タイムズによると、この機能は新聞の見出しをバランスよく整えるために使われていたそうだ。(関連JSコード https://github.com/nytimes/text-balancer)\ 他の例としては https://github.com/adobe/balance-texthttps://github.com/shuding/react-wrap-balancer などがある。

Android側ではすでに適用されている部分もある。(https://cs.android.com/android/platform/superproject/+/master:frameworks/minikin/include/minikin/LineBreaker.h;l=38;drc=5ca657189aac546af0aafaba11bbc9c5d889eab3?hl=ja)

総合的に、広告や新聞、ウェブページなどでテキストの可読性を向上させるために使われてきた機能だと言える。

ダイビング

大体どんな機能なのか、どこから来たのか分かったので、ここで引き返しても大丈夫だ。
ここからは、この機能の最初から最後まで見ていく。

関連するドキュメント資料から見ていこう。

Intent to Ship: CSS healine balancing

「Koji Ishii」がblink-devグループに投稿したメールだ。下に続いてグループ間の議論が展開されている。 まずはKojiのメールから見ていこう。

Specification

https://w3c.github.io/csswg-drafts/css-text-4/#valdef-text-wrap-balance\ csswg-draftsにアップロードされている仕様書だ。

Design doc

https://docs.google.com/document/d/16-T9gqCagJxcST6hcnneSb7qGunxXa37_UHYqMqhPL0/edit?usp=sharing 「Koji Ishii」が作成した技術のデザインドキュメントだ。それほど長くはなく、実装に関する説明が中心となっている。後で確認するとして、続けてメールを見ていこう。

TAG review

https://github.com/w3ctag/design-reviews/issues/822 ここでいうTAGTechnical Architecture Groupの略で、W3Cの技術的な問題に対するレビューを行うグループだ。 このIssueを通じてtext-wrap: balanceに対するレビューが行われた。

基本的な内容は先ほど見た仕様書やデザインドキュメントと同じで、リンクも同じだ。
追加的な内容としてテストに関する情報がある。

https://wpt.fyi/results/css/css-text/white-space?label=master&label=experimental&aligned&view=subtest&q=text-wrap

テストはW3Cが管理するwpt.fyi(Web Platform Tests Dashboard)で行われている。 WPTはWeb Platform Testの略で、ウェブプラットフォームの標準をテストするテストスイートだ。

各テストケースはHTMLファイルに分かれており、このような形で格納されている。

https://github.com/web-platform-tests/wpt/blob/695af8663f/css/css-text/white-space/text-wrap-balance-overflow-001.html

<!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>

もちろんライブで確認することもできる。 https://wpt.live/css/css-text/white-space/text-wrap-balance-overflow-001.html

関連PR https://github.com/web-platform-tests/interop/issues/561

かなり脱線してしまった気がするが、とりあえずメールに戻ろう。

Interoperability and Compatibility

相互運用性と互換性についての話が出てくる。やはりエコシステムのためには他のブラウザとの互換性が重要だ。 Kojiが各ブラウザプロジェクトに対して該当機能についてのスタンスを求めたIssueが添付されている。 実際のエンジンのプロジェクトではなく、standards-positionsのIssueを通じて該当機能に対するスタンスを求めたものだ。

Mozilla(https://github.com/mozilla/standards-positions/issues/755)

このレビューのコメントとして、Mozilla側が仕様書を見て作成したIssueとPRはそれぞれ以下で確認できる。

WebKit(https://github.com/WebKit/standards-positions/issues/143)

AppleのWebKit側はここでバグをトラッキングしている。 https://bugs.webkit.org/show_bug.cgi?id=249840

関連PRはこちらで確認できる。\

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/16723
Provide an initial implementation of `text-wrap: balance` by RWDavid · Pull Request #16723 · WebKit/WebKit

Appleの場合、EWS(Early Warning System)を通じてマージ前に各環境(OS別)のビルド結果を確認できる。
ここで扱う内容ではないので、各自で覗いてみてほしい。
EWSリンク(https://ews-build.webkit.org/#/builders/26/builds/15587)\ EWS(https://github.com/webkit-early-warning-system)

ここまでの道のりを整理してみよう。

KojiのメールをPrimary Sourceとして、この機能の仕様、デザインドキュメント、TAGレビュー、テスト、各ブラウザの互換性に関するIssueを見てきた。 また、各ブラウザごとに該当機能に対するスタンスを求めたIssueとPRを確認した。

本文自体はこのくらいで良いだろう。メールを受け取ったblink-devグループのやりとりの内容を見ていこう。

と思ったのだが、内容がかなり長いし、わざわざ見る必要があるだろうか。
主にパフォーマンス上の問題や、他のプロパティとの関係(white-space)、実装の明確性、機能の制御(最終行の長さを4emにするのか全体の行の最低15%にするのかなど)についての議論が行われた。

大きく取り上げられたIssueだけ要約してみよう。

text-wrapは改行を制御するプロパティだが、これは既存のwhite-spaceと衝突する機能だ。そのため、両者の整理が必要だという話になった。
white-spaceプロパティは空白処理と改行方式を制御するが、text-wrap: balanceのような値を使う場合は、改行のバランスを取る追加的な動作が求められる。
解決策として、white-spaceプロパティがtext-wrapの値も内包できるように、つまりショートハンドとして機能するようにする方法が提案された。

類似の過去の事例としてbaseline-sourceがあり、その場合もvertical-alignと衝突する問題があった。これを解決するためにvertical-alignの値としてbaseline-sourceを使用できるようにする方法が提案された。 [baseline-source] Set baseline-source to auto when vertical-align set.

少し…立ち止まって…

こうしてずっと見てきたが、一つの機能がどれほど多くの過程を経てブラウザに実装されるかが分かった。
しかし、本来の旅はtext-wrap: balanceの仕様と実装についてだった。
関連する仕様や作業について見ているうちに、ここまで来てしまったので、実装についてまとめる気力が尽きてしまった。

仕様書を読んでいるうちに、無数のハイパーテキストの沼にはまってしまったようだ。
それでも、各エンジンのIssueやPRがどこで管理されているか、テストはどこで行われているか。気になる人への道しるべとなれば幸いだ。

というわけで、今回のポストはここまでにして、次回のポストでは実際の実装について見ていくことにする。(資料調査は済んでいる。ご心配なく。)

ではまた。