現場で差がつく `:first-of-type` の真髄:なぜ「最初の子」だけでは不十分なのか
やあ。フロントエンドの現場でコードレビューをしていると、`first-child` を盲目的に使ってしまい、意図しないレイアウト崩壊を引き起こして頭を抱えているジュニアエンジニアをよく見かける。
「あれ、なんで最初だけスタイルが当たらないんだ?」
「いや、`first-child` だと、親要素の直下にある別のタグに負けちゃうんだよ」
こんな会話、聞き覚えはないかな? 今日は、そんな落とし穴を回避し、CSSのセレクタを「使いこなす」側へステップアップするための `:first-of-type` について深掘りしていくぞ。
—
`:first-child` と `:first-of-type` の決定的な違い
まずは仕様の確認だ。多くのエンジニアが混同しがちなこの二つの違いは、「何をもって『最初』と見なすか」という一点に尽きる。
- `:first-child`: 親要素の 「構造上の位置」 を見る。つまり、何であれ「1番目」にいる子要素を指す。
- `:first-of-type`: 親要素の中で 「同じタグ名の要素の中で、最初のもの」 を指す。
この違いがなぜ重要か。それは、現実のマークアップは往々にして「綺麗な兄弟関係」だけでは構成されないからだ。
現場のリアル:型が混在するケース
例えば、ブログ記事のセクションを想像してほしい。
タイトル
序文の段落。
本文の段落。
ここで「最初の段落(p要素)だけにインデントをつけたい」と考えたとき、`p:first-child` を使うとどうなる? 結果は「何も変わらない」。なぜなら、`p` の前に `h2` が鎮座しているからだ。`p` は2番目の子要素なので、`first-child` の条件から弾かれる。
ここで登場するのが `:first-of-type` だ。これは「`p` というタグの中で、最初のもの」を探し当ててくれる。親要素の中に何が混ざっていようが関係ない。その型(Type)の先頭だけをピンポイントで射抜く。 これが実務における強みだ。
—
実践的なサンプルコード:こう書くとスマートだ
実際に現場でよく使う「セクションごとのマージン調整」を例にしよう。見出しと本文が混在するリストにおいて、最初の段落だけ余白を詰めたいケースだ。
.post-body {
/ 基本的に段落には余白を持たせる /
p {
margin-top: 1.5rem;
}
/
ここがミソ!
親要素内の最初のp要素だけ、上部の余白をリセットする
これならh2やdivが先頭にあっても、最初のpは必ず捕まえられる
/
p:first-of-type {
margin-top: 0;
}
}
なぜブラウザはこれを高速に処理できるのか
ブラウザのレンダリングエンジン(BlinkやWebKitなど)は、DOMツリーを構築する際、各要素の「型(タグ名)」を内部的にインデックス化している。`first-of-type` は、該当するタグのリストを走査し、インデックス0番目の要素にスタイルを適用するだけだ。複雑な `nth-child` の計算に比べても、ブラウザにとって非常に負担が少ない処理と言える。
—
現場で「ハマる」ポイント:落とし穴への対策
ここからはシニアの視点だ。`first-of-type` は強力だが、勘違いしやすいポイントが一つある。
それは「親要素を跨がない」という点だ。
もしあなたが `section:first-of-type p` と書いた場合、それは「複数のsectionタグがあるうち、最初のsectionの中にある全p要素」を選択する。しかし、全てのsectionの中にある「最初のp要素」を選択したいなら、セレクタはこう書く必要がある。
/ どのsectionであれ、その中にある最初のp要素をすべて選ぶ /
section p:first-of-type {
font-weight: bold;
}
この「セレクタの組み合わせ」を理解していないと、意図した要素にスタイルが当たらず、結局 `class` をベタ打ちする「CSS地獄」に陥ることになる。
—
まとめ:プロとしてコードを書くために
`first-of-type` は、HTMLの構造が多少複雑化しても、CSS側で柔軟に振る舞いを制御できる、非常に「賢い」セレクタだ。
- 構造に依存しすぎない: `first-child` より柔軟。
- メンテナンス性: HTMLにクラスを追加しなくても、スタイル側で「最初の要素」を制御できる。
- パフォーマンス: ブラウザの負荷が極めて低い。
これから先、君たちが書くCSSが数千行、数万行と増えていく中で、こうした「セレクタの特性を活かした記述」は、コードの行数を減らし、かつ修正に強い設計を作るための強力な武器になるはずだ。
次はぜひ、`:last-of-type` と組み合わせて、「最初と最後だけスタイルを変える」といった応用にも挑戦してみてほしい。何かあればまた相談に乗るから、遠慮なくコードを見せてくれ。現場からは以上だ。

コメント