`:empty`擬似クラスの「嘘」と「真実」:現場でハマらないための実践的知見
現場でコードをレビューしていると、たまに見かけるのが「この要素、空っぽなのにCSSが効いていない(あるいは効きすぎている)」という相談だ。特に`:empty`擬似クラスは、名前こそ直感的だが、ブラウザの「空」の定義が私たちの直感と微妙にズレているために、多くのエンジニアが沼にハマるポイントでもある。
今日は、フロントエンドの現場で「なんとなく」使われがちなこのセレクタについて、ブラウザの裏側の挙動を紐解きつつ、実務で使える堅牢なパターンを共有しよう。
—
`:empty`が「空」とみなす、冷酷なルール
まず前提として、仕様書における`:empty`の定義は極めて潔癖だ。「子要素が一つも存在しないこと(テキストノードも、空白文字も、コメントノードさえも許さない)」。
ここが重要だ。以下のHTMLを見てほしい。
ブラウザのレンダリングエンジンは、DOMツリーを構築する際、空白や改行も一つの「テキストノード」として扱う。つまり、エディタ上でインデントを整えたり、HTMLのタグの間に改行を入れたりしただけで、その要素は「空ではない」と判定されるんだ。
これが、現場で「`:empty`を書いたのにスタイルが当たらない!」と嘆く最大の原因だ。
—
実務で使える:`:empty`の「美しい」活用パターン
では、この気難しいセレクタをどう使いこなすべきか。最も現実的で、かつチームメンバーからも感謝される活用例を紹介する。
1. 空のコンテナに余白を隠す(レイアウト崩れの防止)
CMSから出力されたデータや、動的なAPIレスポンスで「中身がない要素」がDOMに残ってしまうことはよくある。その際、無駄な`padding`や`margin`がレイアウトを押し広げるのを防ぐために使う。
/ 中身が空なら、無駄な余白を消して存在感を消し去る /
.content-wrapper:empty {
display: none;
}
/ 逆に、空の要素に対して「警告」を表示するデバッグ的な使い方も便利 /
.debug-view:empty::after {
content: “※このエリアはデータが空です”;
color: #ff4d4f;
font-size: 12px;
}
2. バッジやステータスの「空」制御
通知バッジなどで、数字がないときは丸い点も表示したくない、というケース。これはロジックで制御するのが理想だが、CSSだけで完結させるなら `:empty` が最もエレガントだ。
.badge {
display: inline-block;
padding: 4px 8px;
background: red;
border-radius: 99px;
color: white;
}
/ 中身が空ならバッジ自体を隠す /
.badge:empty {
display: none;
}
—
「`:empty`の沼」を回避するプロの思考法
中級エンジニアが避けるべきは、「`:empty`が万能だと思い込むこと」だ。以下の2つの回避策は、ぜひ手札に入れておいてほしい。
回避策A:空白文字を許容するなら `:blank`(将来の標準)
実は、FirefoxやChromeの一部で実験的に実装されている`:blank`という擬似クラスがある。これは「空白文字があっても空とみなす」という、我々の直感に近い仕様だ。ただし、現時点では完全なクロスブラウザ対応とは言えないため、基本はJSで `element.innerText.trim() === ”` を判定するか、HTML側のマークアップを極限まで詰める(`
`と一行で書く)のが現実的な「泥臭い」解決策になる。
回避策B:CSSではなくデータバインディングで解決する
ReactやVueを使っているなら、CSSの`:empty`で頑張りすぎるのは逆効果だ。DOMにそもそもレンダリングしないのが正解である。
{/ Reactでの例:そもそも空ならDOMを生成しない /}
{data &&
}
—
まとめ:現場のアーキテクトからのアドバイス
`:empty`は、非常に強力だが、同時に「HTMLの記述形式に極端に依存する」という脆さを持っている。
- HTMLの改行やインデントが結果を左右することを忘れないこと。
- 「CSSだけで解決する」ことに固執しすぎないこと。ロジック(JS)で解決すべきことと、装飾(CSS)で解決すべきことの境界線を見極めるのが、シニアへの第一歩だ。
コードを書くときは、常に「もし将来、この要素の間に誰かが改行を入れたら、このCSSは死ぬのではないか?」と自問自答してほしい。その疑い深さこそが、堅牢なフロントエンドを支える最大の武器になる。
さて、現場に戻ろう。また何か「沼」にはまったら、いつでも聞いてくれ。

コメント