HTMLの「li」の中にdivやpを入れていいのか?―仕様とブラウザの深層心理を紐解く
フロントエンド開発の現場で、ふと手が止まる瞬間。「この`li`要素の中に`div`を突っ込んでも、果たして大丈夫なのだろうか?」という迷い。
HTML5以降、仕様が大幅に緩和されたおかげで、かつてのように「`li`の中身はインライン要素でなければならない」といったガチガチの制約は消え去りました。しかし、仕様書を斜め読みして「何でもあり」と解釈するのは危険です。ブラウザが裏側でどう解釈しているのか、そして「なぜそのマークアップをするのか」という意図まで考えないと、後々アクセシビリティやスタイル調整で痛い目を見るのがこの仕事の常です。
今日は、中級エンジニアなら一度は立ち止まる「`li`要素のコンテンツモデル」について、実務的な視点で深掘りしていきます。
—
1. 仕様が語る真実:`li`は「フローコンテンツ」を受け入れられる
HTMLの仕様上、`li`要素は「フローコンテンツ」を子要素として持つことができます。フローコンテンツとは、平たく言えば`div`、`p`、`h1-h6`、`ul`、`ol`など、ドキュメントの骨組みを作る要素のほとんどを指します。
つまり、技術的には以下のコードは完全に合法です。
-
プロジェクトの進捗
現在、フロントエンドの設計フェーズが完了しました。
ここで重要なのは、「合法だからといって何でも詰め込んでいいわけではない」という点です。
2. ブラウザが裏側で行っている「勝手な解釈」
ブラウザのレンダリングエンジンは、私たちが書いたマークアップが少々おかしくても、可能な限り「良きに計らって」表示しようとします。しかし、`li`の中に複雑なブロック要素を詰め込みすぎると、予期せぬ挙動を招くことがあります。
特に注意すべきは「リストアイテムのマーカー(点)」の位置関係です。
`li`の中に`display: block`な要素(`div`や`p`)を直接入れると、ブラウザによってはマーカーの配置計算が複雑化し、リストのインデントが崩れたり、マーカーがコンテンツの上部に浮いてしまったりする現象が起きることがあります。これはバグではなく、CSSの`list-style-position`の解釈と、ブロックボックスの重ね合わせ(BFC)が複雑に絡み合うことで発生する、現場では「あるある」の仕様の隙間です。
3. 実践的ベストプラクティス:読みやすさと堅牢性の両立
では、どのようにマークアップするのが「プロとして美しい」のか。結論から言うと、「リストの中身が複雑になるなら、その構造を論理的に分離する」ことが鉄則です。
単なる箇条書きではなく、カードUIのようにコンテンツを詰め込む場合は、無理に`li`の中に`div`を入れ子にするよりも、内部の構造を整理してCSSで制御しやすくする工夫が必要です。
以下に、実務でそのまま使える、堅牢でクリーンなサンプルコードを提示します。
-
パフォーマンス最適化
Core Web Vitalsのスコアを改善し、UXを向上させます。
-
アクセシビリティ対応
スクリーンリーダーへの配慮を徹底し、誰にとっても使いやすいUIへ。
4. 最後に:なぜ「構造」にこだわるのか
「動けばいい」というコードは、数ヶ月後の自分やチームメンバーへの借金です。`li`の中に複雑な構造を詰め込む際、もし`ul`を入れ子にするようなケースがあれば、それは「リストの中に別のリストがある」というセマンティクスをブラウザ(そしてスクリーンリーダー)に正しく伝えるチャンスでもあります。
無闇に`div`で囲って構造をフラットにするのではなく、HTMLのタグが持つ意味を活かしつつ、スタイルはCSSの`flex`や`grid`で制御する。このバランス感覚こそが、シニアエンジニアとしての腕の見せ所です。
次に`li`を書くとき、ほんの数秒だけ考えてみてください。「この中身は、本当に一つのリストアイテムとして完結しているか?」と。その問いかけが、あなたのコードをより洗練されたものに変えてくれるはずです。

コメント