大量テキストでの text-wrap パフォーマンス
大規模ページにおける text-wrap: balance と pretty の実測影響、および動的アプリでコストを抑える方法。
詳細な説明
コストモデル
- text-wrap: nowrap / wrap: オーバーヘッドゼロ。レガシーな挙動。
- text-wrap: pretty: 段落あたりほぼ定数のオーバーヘッド(先読みウィンドウ4行)。実用的な段落長では無視できる。
- text-wrap: balance: O(n²) where n は改行候補数。すべての主要ブラウザで 6行までに制限 されるため、それを超えると balance は静かに無効化され、コストは有界。
実測値
Lighthouse 監査と Chrome の Tracing ツールによると、text-wrap: balance を使う H1・H2 が約20個あるページでも、レイアウトパスへの追加コストは1ms 未満です。text-wrap: pretty を使う段落が数百個あるページでも、フォントレンダリングと比べたコストはほぼゼロです。
パフォーマンスが議論になるのは2つのシナリオだけです:
- アニメーション:テキスト幅が毎フレーム動く(60レイアウト/秒)。
- ホットエディットループ:キーストロークごとにリフローするリッチテキストエディタ。
パターン1: アニメーションテキストには balance を避ける
見出し幅をアニメーション(パネルの展開・折りたたみヘッダーなど)させる場合は、pretty またはデフォルト wrap を選んでください。balance を毎フレーム再計算すると、ローエンドデバイスで1〜2ms/フレーム のコストとなり、60fps が50fps まで落ちることがあります。
パターン2: balance を正確にスコープする
balance をグローバルに適用してはいけません:
/* 悪い例 — すべてをバランスする */
* { text-wrap: balance; }
/* 良い例 — 恩恵がある要素にスコープする */
h1, h2, h3, .card-title, .tooltip, .form-label {
text-wrap: balance;
}
パターン3: エディタには stable を使う
text-wrap: stable(Chrome 121+)はライブ編集コンテンツ向けに設計されています。コンテンツが変わっても改行位置を一貫させ、ユーザーのキャレットが飛び回るのを防ぎます。contenteditable 要素に使ってください:
[contenteditable] {
text-wrap: stable;
}
自分のアプリで計測する
Chrome DevTools → Performance を開き、数秒間のインタラクションを記録して、「Layout」エントリを確認します。「text-wrap」がボトムアップサマリーのホットパスに登場する場合は、調査する価値のある実問題があります。99% のケースでは登場しません。
text-wrap: balance が無効化されるのを確認する
非常に狭いコンテナを設定して8行に折り返させ、balance vs デフォルト wrap を比較すれば、6行の上限を確認できます。両者は同じ結果になります。アルゴリズムが高すぎるとブラウザが判断して、balance を静かに切ったのです。
結論
静的ページでは balance と pretty を遠慮なく使ってください。アニメーションとライブ編集ループでは pretty と stable を選んでください。パフォーマンスのために JavaScript のバランス調整にフォールバックするケースは事実上存在しません — ネイティブ CSS 実装の方が速く、シンプルです。
ユースケース
高性能 SPA、リッチテキストエディタ・CMS(キーストロークごとにテキストがリフローする)、見出しがアニメーションするランディングページ、何千ものテキストウィジェットを持つダッシュボード、TTFB と LCP を計測する SSR サイト。