8.

CSS text-indentで字下げ|単位・hanging・each-lineの使い方

編集
この記事の要点
  • text-indent はブロック要素内の最初の行に対する字下げ(インデント)幅を指定する CSS プロパティ
  • 単位は px / em / % など。% は包含ブロックの幅基準
  • 負の値で「左にはみ出す」表現も可能。古典的な画像置換テクニックに使われた
  • hanging キーワードで字下げを反転、each-line強制改行ごとに適用
  • 日本語段落で 1 文字下げたいなら text-indent: 1em がもっとも自然

text-indent とは

text-indent は、ブロック要素内の最初の行のテキストをどれだけ字下げするかを指定する CSS プロパティです。論文や小説などで使われる「段落の冒頭 1 文字下げ」を CSS で再現するときの定番です。

基本構文

セレクタ {
  text-indent: 値;
}

/* 例: 段落の冒頭を 1 文字下げる */
p {
  text-indent: 1em;
}

使える単位

単位意味
px固定ピクセル。フォントサイズに追従しない
em当該要素のフォントサイズ基準。1em = 文字 1 個分
remルート要素のフォントサイズ基準
%包含ブロックの幅基準(要素自身の幅ではない)
ch「0」の幅基準。等幅フォントで字数指定に便利

日本語段落の典型

日本語の本文は「冒頭 1 字下げ」が一般的です。1em 指定が読みやすく、フォントサイズが変わっても比率が保たれます。

article p {
  text-indent: 1em;
  line-height: 1.8;
  margin-bottom: 0.5em;
}

負の値(左にはみ出す)

負の値を指定すると、最初の行が要素の左端より外側にはみ出して表示されます。リストの「・」の代わりに見出し記号を使う表現や、画像置換テクニックで使われます。

.hanging-quote {
  padding-left: 1.5em;
  text-indent: -1.5em;  /* ぶら下げインデント */
}
/* 出力:
   "First line is not indented,
    but the rest are aligned." */

古典的な画像置換テクニック

かつてはロゴ画像の上にテキストを置く際、テキストを画面外に飛ばすため大きな負の値を使うテクニックがありました。SEO・アクセシビリティの観点では現代では非推奨で、aria-label など別の手段が推奨されます。

.logo {
  background: url(logo.png) no-repeat;
  width: 200px;
  height: 60px;
  text-indent: -9999px; /* 画面外に飛ばす */
  overflow: hidden;
}

hanging キーワード

CSS Text Level 4 で hanging キーワードが追加されました。指定すると意味が反転し、最初の行を字下げせず、それ以降の行を字下げします。

.hanging {
  text-indent: 2em hanging;
}
/* 1 行目: そのまま
   2 行目以降: 2em 字下げ */

each-line キーワード

each-line は強制改行(<br> や段落の暗黙改行)ごとに字下げを適用します。文章途中で改行が入る詩のレイアウトなどで便利です。

.poem p {
  text-indent: 1em each-line;
}

% 指定の挙動

%包含ブロックの幅を基準にします。要素自身の幅ではない点に注意してください。

.container {
  width: 600px;
}
.container p {
  text-indent: 10%; /* 600px の 10% = 60px */
}

typical use cases

段落の冒頭字下げ(標準)

article > p {
  text-indent: 1em;
}

最初の段落だけ字下げしない(雑誌スタイル)

article > p:first-of-type {
  text-indent: 0;
}
article > p {
  text-indent: 1em;
}

ぶら下げインデント(コードリストの注釈など)

.note {
  padding-left: 2em;
  text-indent: -2em;
}

注意点

インライン要素には効かない

text-indent はブロックレベル要素のみ有効です。インライン要素(<span> など)に指定しても効果はありません。

ボタン・フォーム部品はやや特殊

<input type="text"><button> にも効きますが、ブラウザ実装が分かれるため、入力欄の左パディングは padding-left を使う方が無難です。

flex / grid アイテムの注意

flex / grid の子要素はブロック扱いになるので text-indent は機能しますが、内部のテキストノードが折り返さないと効果が見えません。期待通りでないときは display を確認してください。

アクセシビリティ

負の大きい値(-9999px など)でテキストを画面外に飛ばす手法は、画面リーダーには読み上げられるものの、SEO 観点で隠しテキスト扱いを受けるリスクがあります。現代では以下が推奨されます。

  • アイコンボタンには aria-label や visually-hidden ユーティリティ
  • 背景画像の代替テキストには img + alt を選ぶ
  • 装飾だけのテキスト隠しは position: absolute; clip-path: inset(50%); 等の安全なテク

padding-left との違い

text-indentpadding-left はどちらも「左側に空きを作る」効果がありますが、対象範囲が異なります。

プロパティ影響範囲用途
text-indent最初の行のテキストのみ段落の冒頭字下げ
padding-left全ての行(要素のコンテンツ領域全体)左に均一なスペース
margin-left要素自体の左マージン要素全体を右にずらす

「2 行目以降も含めて全部下げたい」場合は padding-left または margin-left、「1 行目だけ字下げ」したい場合は text-indent と覚えると整理しやすいです。

古いブラウザでの対応

text-indent 自体は CSS1 から存在する古典的なプロパティで、対応していないモダンブラウザはまずありません。一方 hangingeach-line キーワードは比較的新しい仕様で、IE11 や古い Safari では未対応です。ターゲットブラウザの対応状況はcaniuse.com で確認しましょう。

よくあるトラブル

症状原因と対処
字下げされないインライン要素に指定している / 親で 0 に上書きされている / display:flex の中で意図しない構造になっている
2 行目以降も下がる仕様通り(最初の行のみ字下げ)。each-line キーワード追加で改行ごと適用
% が想定と違う幅包含ブロック幅基準。要素自身の幅ではない点に注意し、直接親要素の幅で計算
flex 子要素で効かない子要素がインライン化されている。display:block や子要素のラップ構造を確認
負の値で文字が消えるoverflow:hidden + 大きな負の値で画面外に押し出している。アクセシビリティ的に推奨されないので別手段に置き換え
hanging キーワードが効かない古いブラウザ(IE 系)は未対応。padding-left + 負の text-indent で代替

FAQ

Q: 改行(br)の後も字下げしたい
A: each-line キーワードを追加すると、強制改行ごとに字下げが適用されます。

Q: ぶら下げインデントの推奨実装は?
A: padding-left と負の text-indent の組み合わせが最も互換性が高い書き方です。

Q: 字下げ量を文字数で指定したい
A: em 単位を使えば「N 文字分」と読めます。等幅フォントを前提とするなら ch でも可。

関連

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. text-decoration関連のプロパティ
  2. word-breakプロパティ
  3. hyphensプロパティ
  4. white-spaceプロパティ
  5. text-alignプロパティ
  6. vertical-alignプロパティ
  7. line-heightプロパティ
  8. text-indentプロパティ
  9. letter-spacingプロパティ
  10. word-spacingプロパティ
  11. text-transformプロパティ
  12. directionプロパティ
  13. unicode-bidiプロパティ

最近更新/作成されたページ