z-index は重なり合う要素の奥行きの重ね順を制御します。値が高いほど前面に表示されます。ただし、配置された要素でのみ機能し、スタッキングコンテキスト内で動作します。これが z-index の混乱の主な原因です。
css
{ : fixed; : ; }
{ : fixed; : ; }
{ : relative; : ; }
z-index は position: static(デフォルト)では無視されます。要素は relative、absolute、fixed、または sticky である必要があります。
スタッキングコンテキストは自己完結した「レイヤー」です。z-index の値は同じコンテキスト内でのみ競い合います。子要素は、その z-index がどんなに高くても、親のスタッキングレベルを超えることはできません。
.parent-a { position: relative; z-index: 1; }
.parent-b { position: relative; z-index: 2; }
.child-of-a { position: absolute; z-index: 9999; }
/* ❌ child-of-a STILL renders below everything in parent-b, */
/* because parent-a (z-index 1) is entirely below parent-b (z-index 2). */
これは典型的な「z-index: 9999 のモーダルが何かの後ろに隠れている」というバグです。モーダルがより低いレイヤーにある親にトラップされています。
多くのプロパティが暗黙的にスタッキングコンテキストを作成し、子孫をトラップできます:
- position + z-index (other than auto)
- opacity less than 1
- transform, filter, will-change
- isolation: isolate
- a flex/grid item with z-index
/* render the modal at the document root (outside trapping parents) — "portal" */
.isolated { isolation: isolate; } /* deliberately create a context where you want one */
実際には、モーダル/ツールチップを DOM のトップで描画してください(React ポータルなど)。これにより、低いレイヤーの親にトラップされません。
スタッキングコンテキストは最も困惑する z-index のバグを説明します。極めて高い z-index でも、その祖先がより低いレイヤーにあるために負けることがあります。
opacity、transform、配置された z-index がコンテキストを作成すること、そして子要素がそれらから脱出できないことを知ることで、オーバーレイ/ドロップダウンの順序をデバッグし、DOM(ポータル)を正しく構造化できます。
ジュニアからシニアまで、詳細な回答付きのIT面接質問ライブラリ。
寄付する