テキストの正確な配置

ウェブ機能: text-box

問題

ブラウザは、行の高さや、アセンダーやディセンダーなどのフォント固有の指標に対応するため、テキスト文字の上下に余分な空白を自動的に追加します。この「ゴースト スペース」により、標準の CSS を使用してピクセル単位で垂直方向に揃えることができなくなります。

一般的な問題としては、次のようなものがあります。

  • アイコンの位置がずれる: align-items: center を使用している場合でも、テキストが隣接するアイコンよりも視覚的に低くまたは高く表示されます。
  • 不正確なパディング: padding: 12px を含むボタンは、フォントの内部レディングにより、上部または下部に余分なスペースがあるように見えます。
  • フラッシュ配置: 「マジック ナンバー」の負のマージンを使用しないと、大文字の上部をコンテナまたは隣接する画像の上部に正確に揃えることはできません。

ソリューション

text-box-trim プロパティと text-box-edge プロパティ(短縮形 text-box)を使用すると、特定のフォント指標に基づいてこの内部レディングをトリミングできます。テキスト ボックスを cap-height(大文字の上部)と alphabetic baseline(ほとんどの文字の下部)にトリミングすることで、要素の境界ボックスを視覚的なコンテンツに合わせることができます。

実装戦略

  1. 必須: テキストを含む要素に text-box-trim: trim-both(または text-box の省略形)を適用します。
  2. 必須: text-box-edge でトリミングに使用する指標を指定します。ほとんどの UI 配置には cap alphabetic を使用します。
  3. 推奨: flex コンテナまたは grid コンテナで視覚的に垂直方向の中央揃えを実現するために使用します。
  4. 推奨: CSS の padding 値がテキストとコンテナの端の間の視覚的なギャップと一致するようにします。
  5. 読みやすさのために従来の行間が必要な長文の本文には使用しないでください。見出し、ボタン、UI ラベルに最適です。

実装ガイド

ユースケース 1: バッジの内部の先頭部分をトリミングする

フォントによって、テキストの上下に組み込まれているスペースの量が異なります。これにより、デザインを一致させたり、バッジ内のテキストを視覚的に中央に配置したりすることが難しくなる場合があります。コンテナのパディングをテキストにぴったり合わせる場合は、text-box: trim-both cap alphabetic を使用します。これは、バッジやタグなどの高密度の UI コンポーネントに特に役立ちます。これにより、パディングがすべての辺のテキストの端から始まるようになります。

.badge {
  padding: 10px;
  background: hotpink;
  border-radius: 10px;
  /* 
    Trims the top to the cap-height and 
    the bottom to the alphabetic baseline.
  */
  text-box: trim-both cap alphabetic;
}

ユースケース 2: アイコン付きの中央揃えテキスト

Flexbox を使用してテキストとアイコンを配置すると、「ゴースト スペース」によってテキストが少し中央からずれているように見えることがよくあります。ボックスをトリミングすると、レイアウト エンジンは実際に表示される文字の高さを使用して配置を行います。

.button {
  display: inline-flex;
  align-items: center;
  gap: 8px; 
}
/* 
  text-box does NOT inherit, and must be applied directly to the text element.
*/
.button-text{
  /* 
    The flex container now centers against the 
    visible letters, not the invisible font box.
  */
  text-box: trim-both cap alphabetic;
}

ユースケース 3: テキストを上端に揃える

見出しを隣接する画像や装飾要素の上部に完全に揃えるには、trim-start cap alphabetic を使用します。終了位置はトリミングされませんが、終了位置を定義する必要があります。

.hero {
  display: flex;
  align-items: flex-start;
}

h1 {
  /* MANDATORY: The bottom edge must also be defined, even though only the top is trimmed. */
  text-box: trim-start cap alphabetic;
}

ベスト プラクティス

  • 推奨事項: 簡潔にするために text-box の省略形(text-box: <trim-direction> <edges>)を使用します。
  • 推奨: 1 つのエッジのみをトリミングする場合でも、常に両方のエッジを指定します(デフォルトの text エッジを使用する場合を除く)。
  • 推奨: line-height と組み合わせて、間隔を調整します。トリミングを行うと、テキストの最初の行の前と最後の行の後の行間が削除されますが、line-height は複数行テキストの行間の距離に影響します。
  • すべての要素に適用しないでください。精密な位置合わせが必要な場合にのみ使用してください。

代替戦略

text-box はプログレッシブ エンハンスメントです。サポートしていないブラウザでは、テキストはデフォルトの行送りでレンダリングされます。レイアウトは引き続き機能しますが、精度が若干低下します。古いブラウザではプロパティが安全に無視されるため、特別なフォールバック コードは必要ありません。

その他の注意事項

  1. フォントの指標: フォントによって内部指標が異なります。cap alphabetic は信頼性の高いデフォルトですが、フォントやユースケースによっては、小文字の配置を改善するために ex(x-height)が必要になる場合があります。
  2. 複数行のテキスト: トリミングはブロックの最初の行と最後の行に適用されます。内部回線は影響を受けません。