やあ。フロントエンドの迷宮で日々CSSと格闘している君たちへ。
今日は「構造的疑似クラスの基本中の基本」である `:first-child` について話そうと思う。
「そんなのMDNを見れば一発だろ?」と思った君、ちょっと待ってくれ。確かに仕様は単純だが、「CSSのセレクタを正しく理解し、ブラウザの描画コストを意識して書く」ことと、「なんとなく動くから書いている」ことの間には、実務レベルでは天と地ほどの差があるんだ。
今日は、中級エンジニアの君たちが明日から現場で胸を張って使える、 `:first-child` の本質的な知見を共有する。
—
:first-child の本質と「勘違い」の罠
`:first-child` は、「親要素内の最初の子要素」を選択する。これ自体は正しい。だが、初心者が陥りがちなのが「セレクタの対象が何なのか」という混同だ。
例えば、以下のような構造があるとする。
最初の段落
二番目の段落
ここで `.container p:first-child` と書けば、最初の `
` が選択される。ここまではいい。では、こうだったらどうだ?
タイトル
最初の段落
この場合、`.container p:first-child` は何も選択しない。なぜなら、`.container` の最初の子要素は `
` であり、`
` は `p` ではないからだ。
現場で「なぜかスタイルが当たらない」と首を傾げるバグの多くは、この「要素名(タグ名)の判定」と「子要素の順番」の認識ズレから発生する。`:first-child` は「型」と「位置」の両方をシビアに見ているということを、まずは肝に銘じてほしい。
—
ブラウザはどう処理しているのか?(パフォーマンスの視点)
CSSセレクタは、ブラウザにとって「右から左」へと解析される。
`:first-child` を含むセレクタに遭遇したとき、ブラウザはまず対象の要素(例えば `p`)を見つけ、その親要素を特定し、「その親の最初の子がこの要素と一致するか?」という条件を再帰的にチェックしているんだ。
複雑なDOMツリーの中でこれを乱用すれば、当然ブラウザの計算コストは上がる。特に大規模なアプリケーションで、深い階層の `:first-child` を多用するのは避けたい。しかし、逆に言えば、「特定の子要素にだけマージンを消す」といった処理においては、JSでクラスを付け替えるよりも、CSSに任せた方が圧倒的に高速でメモリ効率も良い。
CSSの構造的疑似クラスは、ブラウザがネイティブで最適化している処理だ。JSでDOMを操作してクラスを付与する前に、まずはCSSで解決できないか考える。これがフロントエンドのプロの思考だ。
—
実践:リストのセパレーター問題
現場で最もよく使うパターンを一つ紹介しよう。リストの各要素の間に境界線を引きたいとき、どう書いている?
/ 悪い例:全要素にボーダーを引いて、最後を消す /
.list-item { border-bottom: 1px solid #ccc; }
.list-item:last-child { border-bottom: none; }
/ 良い例:最初の要素以外にボーダーを引く(あるいは逆) /
.list-item + .list-item { border-top: 1px solid #ccc; }
実は `:first-child` を使ったこんなアプローチも非常にクリーンだ。
/ 実務で使える:最初の要素以外にマージンを持たせる /
.card-item {
margin-top: 20px;
}
/ 最初の要素だけは、親の余白と被るのを避けるためにマージンをリセットする /
.card-item:first-child {
margin-top: 0;
}
この手法は、モダンなレイアウト(FlexboxやGrid)においても非常に重宝する。要素の間に `gap` が使えないレガシーな環境や、複雑なレスポンシブデザインにおいては、この「最初の要素だけリセットする」という書き方は、僕のCSSアーキテクチャの基本戦略の一つだ。
—
まとめ:明日からの君へ
`first-child` は単なる便利機能じゃない。「DOMの構造に対する意思表示」なんだ。
1. 「型」を意識せよ: セレクタは「何が」「どこにあるか」を明確に指定すること。
2. JSに頼るな: 表示制御のロジックは可能な限りCSSに押し込める。それがブラウザのパフォーマンスを最大化する鍵だ。
3. 余白管理の武器にせよ: `margin` や `border` を制御する際、`first-child` を使って「最初だけ例外を作る」という考え方は、コードを驚くほどシンプルにしてくれる。
CSSは、書いた人の「論理性」がそのままコードの美しさに直結する言語だ。
次に `:first-child` を書くとき、その裏でブラウザがどう動いているか、少しだけ想像してみてほしい。そうすれば、君の書くコードは一段階上のクオリティに到達するはずだ。
また現場で会おう。質問があればいつでも聞いてくれ。

コメント