【テクニカル・上級編】writing-modeとインライン要素の配置 – HTML実践ガイド

縦書きの深淵:`writing-mode`とインライン要素が織りなすレンダリングの罠

Webというプラットフォームは、長らく「横書き」という前提に支配されてきました。しかし、日本語の組版や芸術的なレイアウトを追求する際、`writing-mode: vertical-rl`は避けて通れない関門です。

「縦書きにすれば勝手に回転するだろう」という安易な期待は、CSSOMの構築やブラウザのレンダリングパイプラインを深く理解していない証拠です。インライン要素(`a`, `span`, `strong`, `code`など)が縦書き環境下でどのように配置され、それがなぜパフォーマンスやレイアウト崩壊の温床となるのか。現場の知見を交えて紐解いていきましょう。

1. 縦書きにおける「インライン」の再定義

`writing-mode: vertical-rl`を適用した瞬間、ブロック軸(Block Axis)とインライン軸(Inline Axis)は90度回転します。このとき、ブラウザのレイアウトエンジンは、インライン要素を「行の高さ」ではなく「文字の並び」として処理し直します。

ここで注意すべきは、フォントメトリクスとベースラインの挙動です。特に `strong` や `em` で装飾された箇所は、フォントのウェイトやスタイル(イタリック)によって、レンダリング時に「グリフの境界ボックス」が微妙に変化します。

パフォーマンスへの影響:リフローの抑制

インライン要素の装飾を頻繁に切り替える場合、`writing-mode`が適用されていると、計算負荷は横書きよりも高くなる傾向があります。なぜなら、縦書き環境では「文字の回転(`text-orientation`)」と「文字ごとの位置補正」が計算式に含まれるためです。不要な再計算を避けるため、アニメーションや頻繁なDOM操作が伴う箇所には、必ず `contain: layout style;` を付与し、レンダリングのスコープを局所化してください。

2. 縦書き環境でのエッジケースとハック

縦書きにおける最大の敵は、`code`タグや`time`タグに見られる「数字の扱い」です。

/ 縦書きで数字を正しく表示するための防衛的アプローチ /
.vertical-text {
writing-mode: vertical-rl;
/ 数字を縦書きの中で横向き(等幅)に見せるための定石 /
text-combine-upright: all;
/ フォントのグリフ調整。縦書き特有のレンダリング崩れを防ぐ /
font-feature-settings: “vpal”, “vhal”;
}

特に `time` 要素などで日時を表示する場合、`text-combine-upright` を使用すると、内部的にブラウザは「1文字分の領域に複数の数字を押し込む」という特殊なレンダリングを行います。これがCSSの `line-height` 計算を狂わせ、結果としてリフローを誘発するケースがあります。上級エンジニアとしては、これらを「単なる装飾」ではなく「レイアウト計算の変数」として捉える必要があります。

3. TypeScriptによる型安全なインライン管理

デザインシステムを構築する際、コンポーネントが「現在どの書き込みモードにいるか」を型レベルで担保することは、堅牢なアプリケーションの第一歩です。

type WritingMode = ‘horizontal-tb’ | ‘vertical-rl’ | ‘vertical-lr’;

interface TextProps {
content: string;
// 縦書き特有の崩れを防ぐためのバリデーション用フラグ
isVertical?: boolean;
}

/

  • 縦書き環境において、インライン要素の競合を防ぐためのラッパー関数
  • レイアウトの非同期的なズレを回避するため、計測値をキャッシュする戦略を推奨

/
const getSafeLineHeight = (isVertical: boolean): string => {
// 縦書き時は物理的な高さよりもインライン軸のスペースを優先的に計算する
return isVertical ? ‘1.5em’ : ‘1.8’;
};

4. 非同期読み込みとレンダリングの競合

Webフォントを非同期で読み込んでいる場合、フォントの切り替わり(FOUT)は、縦書きレイアウトにおいて致命的な崩れを引き起こします。横書きであれば行間が広がるだけで済むことがありますが、縦書きでは「文字の回転」と「行のシフト」が同時に起こり、視覚的なジャンプが非常に大きくなります。

回避策:

  • `font-display: swap;` だけでなく、`size-adjust` を駆使して、フォント読み込み前後で文字の占有サイズを極限まで近づける。
  • インライン要素に対して `white-space: nowrap;` を適切に配置し、フォント読み込み中の行分割を強制的に制限する。

まとめ:エンジニアとして持つべき視座

`writing-mode` を使いこなすということは、ブラウザというブラックボックスの「物理的制約」を理解することと同義です。

1. グリフは常に可変である: `strong` や `code` で装飾されたインライン要素は、ブラウザにとって特別な計算コストを強いるノードであると認識する。
2. 計測値の信頼性を疑う: DOMの `getBoundingClientRect()` は、縦書き環境下では座標系が回転しているため、横書き用のロジックで計算すると重大なバグを生みます。常に `offsetParent` を基準とした計算を心がけてください。
3. 最適化は局所的に: グローバルなCSSで `writing-mode` を適用せず、可能な限りコンポーネント単位でカプセル化し、リフローの影響範囲を最小化する。

WebのUIは、ただ表示されれば良いのではありません。その背後で動くレンダリングエンジンを掌の上で転がすような、緻密な設計こそが、我々エンジニアの矜持なのです。縦書きという「制約」を「武器」に変える実装を、次のプロダクトでぜひ試してみてください。

コメント

タイトルとURLをコピーしました