CSSで、段落の1文字目を大きくする方法

​​CSS​HTML,Playwright

段落の1文字目を大きくして、何行かにまたがらせるには、::first-letter で1文字目を選びます。大きさの付け方は2通りあります。float: left で左に寄せて font-size で大きくする書き方は、Chrome、Firefox、Safari のどれでも使えます。initial-letter: 3 のように行数で指定する書き方は、Chrome 110 以降で使えます(Safari は接頭辞付き、Firefox は未対応)。日本語の段落で initial-letter に3以上を指定すると、試した条件の多くで指定より1行多く字下げされたので、その直し方も載せます。

補足

検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。フォントは Noto Sans CJK JP、本文は16px、行の高さは1.8(28.8px)、段落の幅は320pxにしました。ページを Playwright で開き、2文字目以降を1文字ずつ囲んで位置を取り、何行目までが右にずれたか(字下げされたか)を数えました。画面も撮って、大きくした1文字目と本文の文字の上端・下端を画素で測りました。Firefox と Safari、スマートフォンの実機、ほかのフォントでは試していません。

float で1文字目を左に寄せる

::first-letter は、ブロックコンテナー(p や div など)の最初の行の、最初の文字を選ぶ擬似要素です。ここに float: left と大きな font-size を指定すると、1文字目が左に寄り、続く文章がその右に回り込みます。

css
/* 段落の1文字目を大きくして、左に回り込ませる(float を使う書き方) */
.drop-float::first-letter {
  float: left;
  font-size: 5em;
  line-height: 1;
  margin-right: 0.1em;
  color: #067a98;
  font-weight: 700;
}
html
<p class="drop-float">猫の手も借りたいほど忙しい日でも、……</p>

::first-letter はブロックコンテナーにしか効きません。検証でも、1文字目を濃い水色にして3行分に大きくする指定(次の節で使う drop-initial クラス)を、display: inline のままの span に付けたところ、1文字目の色も大きさも変わりませんでした。

::first-letter に使えるプロパティは決まっていて、フォント、色、背景、margin、padding、border、float などです。一覧は MDN の ::first-letter の「利用可能なプロパティ」にあります。

上下2段の比較。1行ごとに薄い水色と白の帯を敷いた段落。上の「font-size: 3.4em」では、濃い水色の大きな「猫」の右に2行が回り込み、3行目からは左端から始まっている。下の「font-size: 5em」では、より大きな「猫」の右に3行が回り込み、4行目から左端に戻っている
float の書き方では、font-size で何行分になるかが決まる

line-height: 1 にしておくと、1文字目の箱の高さは font-size と同じになります。本文の行の高さが28.8pxのとき、font-size: 5em(80px)なら3行分の高さ(86.4px)に収まり、字下げされたのは3行でした。3.4em(54.4px)では2行です。

1文字目の高さが本文の行の何行分にあたるかで、字下げされる行の数が変わります。font-size を変えて数えた結果は次のとおりです。

1文字目の font-size 字下げされた行
2.4em〜3.6em(38.4〜57.6px) 2行
4em、5em(64px、80px) 3行
5.4em〜5.8em(86.4〜92.8px) 4行

ちょうど2行分の57.6px(3.6em)では2行のままでしたが、ちょうど3行分の86.4px(5.4em)では4行になりました。境目ちょうどの値は結果がそろわないので、行の高さの倍数より少し小さめにします。

5em のとき、大きな「猫」の上端は本文1行目の文字の上端と1px、下端は3行目の文字の下端と1pxしか違わず、3行の文字の高さにほぼぴったり重なりました。

initial-letter で何行分にするかを指定する

initial-letter は、1文字目が何行分を占めるかを数で指定するプロパティです。font-size を計算しなくても、行数を書くだけで大きさが決まります。

css
/* 1文字目を3行分の高さにする(initial-letter を使う書き方) */
.drop-initial::first-letter {
  initial-letter: 3;
  margin-right: 0.1em;
  color: #067a98;
  font-weight: 700;
}

英語の段落では、指定どおり3行が字下げされました。大文字の「C」の上端は、1行目の文字の上端と同じ位置でした。

ところが、日本語の段落に同じ CSS を当てると、字下げされた行は4行でした。大きな「猫」の字形は3行目の行の下端(86.4px)より上で終わっているのに、4行目も「猫」の幅だけ右にずれます。上端も、1行目の文字より9px上から始まりました。

上から3段の比較。1行ごとに薄い水色と白の帯を敷いた段落。「英語の段落、initial-letter: 3」は、大きな「C」の右に3行が回り込んでいる。「日本語の段落、initial-letter: 3」は、大きな「猫」の右に4行が回り込み、4行目の帯がピンクの枠で囲まれ「4行目」と書かれている。「日本語の段落、margin-bottom: -4px を足す」は、「猫」の右に3行が回り込み、4行目は左端から始まっている
日本語の段落では4行目まで字下げされる(2段目)。margin-bottom: -4px で3行に収まる(3段目)

本文の大きさと行の高さを5通りに変えて数えると、英語の段落はどれも指定した行数でした。日本語の段落は、initial-letter: 2 ではどれも2行でしたが、3 では5通りのうち4通りで4行になりました。4 と 5 は5通りすべてで、指定より1行多くなりました。

日本語の段落は margin-bottom を少し引いて直す

1文字目の margin-bottom に小さな負の値を付けると、指定した行数に戻りました。

css
/* 日本語の段落で、1文字目の下の余白を少し詰めて、3行に収める */
.drop-initial.ja-fix::first-letter {
  margin-bottom: -4px;
}
html
<p class="drop-initial ja-fix">猫の手も借りたいほど忙しい日でも、……</p>

initial-letter: 3 では、本文16px・行の高さ1.5、16px・1.8、18px・2.0 のどれでも、-2px から -24px までの値で3行に収まりました。引きすぎると、16px・1.8では -30px から2行に減りました。-4px は、試した3つの条件すべてで3行になった値です。

16px・1.8の段落では、initial-letter: 4 なら -6px、5 なら -8px まで引くと、指定した行数になりました。行数が多いほど、大きく引く必要がありました。

initial-letter が使えないブラウザに備える

MDN の互換性データ(@mdn/browser-compat-data 8.1.8)では、initial-letter は Chrome 110 から使え、Firefox は未対応です。Safari は -webkit-initial-letter という接頭辞付きの名前で対応しています。MDN の initial-letter のページにある互換性の表も、このデータをもとに作られています。

そこで、ふだんは float の書き方にしておき、@supports で initial-letter が使えるときだけ切り替えます。@supports は、ブラウザがその CSS の機能に対応しているときだけ、中の宣言を使う書き方です。

css
/* initial-letter が使えないブラウザでは、float の書き方にする */
.drop::first-letter {
  float: left;
  font-size: 5em;
  line-height: 1;
  margin-right: 0.1em;
  color: #067a98;
  font-weight: 700;
}
@supports (initial-letter: 3) {
  .drop::first-letter {
    float: none;
    font-size: inherit;
    line-height: inherit;
    initial-letter: 3;
    margin-bottom: -4px;
  }
}

Chromium 153 では CSS.supports("initial-letter: 3") が true で、@supports の中が使われました。字下げは3行で、margin-bottom: -4px を付けた initial-letter の段落と同じ位置になりました。@supports の中では、外側で指定した float や font-size を元の値に戻してから、initial-letter を指定しています。

機能 Chrome Firefox Safari
::first-letter 1 1 1
initial-letter 110 未対応 9(-webkit- 付き)
@supports 28 22 9

かぎかっこで始まる段落では、記号も一緒に大きくなる

段落が「「」のような記号で始まると、::first-letter はその記号と次の文字をまとめて選びます。MDN の ::first-letter に、最初の文字のすぐ前後にある記号も範囲に含まれると書かれています。

かぎかっこで始まる段落に initial-letter: 3 と margin-bottom: -4px を当てた画面。1行ごとに薄い水色と白の帯を敷いている。濃い水色の大きな「「」と「猫」が並び、「猫」は3行分の高さを占め、その右に3行が回り込み、4行目は左端から始まっている
かぎかっこと「猫」の2文字が、まとめて大きくなった

initial-letter: 3 と、上の margin-bottom: -4px を当てた段落で試すと、かぎかっこ「「」と「猫」の2文字が大きくなりました。続く3行の字下げの幅も、「猫」1文字のときの92pxから127pxに広がりました。かぎかっこを大きくしたくないときは、段落の先頭に記号を置かない文にします。

​Posted by 86