CSSのプロパティz-indexは要素の重なり順を制御するために使われますが、「z-indexが効かない!」という状況に遭遇したことはありませんか?その原因の多くはスタックコンテキストです。
この記事では『z-index』と『スタックコンテキスト』について、以下の内容を図とサンプルコードを用いてわかりやすく解説します。
z-indexが効かない例- スタックコンテキストとは
z-indexとスタックコンテキストの関係
z-indexが効かない例
z-indexを設定しているのに期待通りに動作しない場合があります。以下のサンプルコードと実行結果を見てみましょう。
<div class="container">
<div class="rect div-1">.div-1 ( z-index: 1 )</div>
<div class="rect div-2">
.div-2 ( z-index: 2 )
<div class="rect div-2-1">.div-2-1 ( z-index: 21 )</div>
<div class="rect div-2-2">.div-2-2 ( z-index: 22 )</div>
</div>
<div class="rect div-3">.div-3 ( z-index: 3 )</div>
</div>.container {
color: white;
position: relative;
}
.rect {
width: 250px;
height: 100px;
position: absolute;
}
.div-1 {
background-color: red;
top: 0;
left: 0;
z-index: 1;
}
.div-2 {
background-color: green;
top: 50px;
z-index: 2;
}
.div-2-1 {
background-color: blue;
top: 20px;
left: 200px;
z-index: 21;
text-align: right;
}
.div-2-2 {
background-color: orange;
top: 70px;
left: 200px;
z-index: 22;
text-align: right;
}
.div-3 {
background-color: purple;
top: 100px;
z-index: 3;
}
これをブラウザで開くと以下のように表示されます。

z-indexの値の大きさは.div-1→.div-2→.div-3→.div-2-1→.div-2-2ですが、.div-3が最前面に表示されています。これはスタックコンテキストが原因です。
スタックコンテキストとは
CSSには「スタックコンテキスト(重ね合わせコンテキスト)」という概念があります。
スタックコンテキストは、CSSで要素の重ね順(z-index)を制御する際の独立した空間のようなものです。z-indexを設定して要素の重なり順をコントロールする場合、スタックコンテキスト内でしか効果を発揮しません。
スタックコンテキストを生成するための条件はいくつかあります。例えば、以下の要素はスタックコンテキストを生成します。
positionの値がabsoluteまたはrelativeであり、かつz-indexの値がauto以外の要素- 例:
position: relative; z-index: 1;
- 例:
positionの値がfixedまたはstickyの要素- 例:
position: fixed;
- 例:
例えば、ある要素の「positionの値がabsoluteまたはrelativeであり、かつz-indexの値がauto以外」の場合、この要素はスタックコンテキストを生成し、その中に含まれる子要素は、このスタックコンテキスト内でのみz-indexを影響を受けます。
冒頭に示したサンプルコードにおいて、.div-2は新しいスタックコンテキストを生成しています。そのため、.div-2-1や.div-2-2は、.div-2内でのみz-indexの値が有効です。一方、.div-3は、.div-2の外側にあるルートスタックコンテキストに所属しているため、.div-2-1や.div-2-2よりも上に表示されます。
html要素はデフォルトでルートスタックコンテキストを生成しているため、すべての要素は何らかのスタックコンテキストに所属しています。
MDN
スタックコンテキストに関しては以下のMDNのページに詳しく記載されています。
補足
- スタックコンテキストは「スタッキングコンテキスト」や「重ね合わせコンテキスト」や「スタック文脈」とも言います。
.div-1,.div-2,.div-2-1,.div-2-2,.div-3はすべて新しいスタックコンテキストを生成しています。
z-indexとスタックコンテキストの関係
z-indexは要素の重なり順を制御するプロパティですが、その要素が所属するスタックコンテキストの中でのみ有効です。冒頭に示したサンプルコードを表に示すと以下のようになります。
| クラス名 | z-index | 所属するスタックコンテキスト | 重なり順のイメージ |
.div-1 | 1 | html(ルートスタックコンテキスト) | root > 1 |
.div-2 | 2 | html(ルートスタックコンテキスト) | root > 2 |
.div-2-1 | 21 | .div-2(新しいスタックコンテキスト) | root > 2 > 21 |
.div-2-2 | 22 | .div-2(新しいスタックコンテキスト) | root > 2 > 22 |
.div-3 | 3 | html(ルートスタックコンテキスト) | root > 3 |
.div-2-1 や .div-2-2 の z-index がどれだけ大きくても、 .div-3の上に重なることはありません。これは.div-2-1 と.div-2-2が .div-2 のスタックコンテキスト内に限定されているからです。そのため、最終的な重なり順は.div-1→.div-2→.div-3→.div-2-1→.div-2-2となります。
本記事のまとめ
この記事では『z-index』と『スタックコンテキスト』について、以下の内容を説明しました。
z-indexが効かない原因z-indexは所属するスタックコンテキスト内でのみ効果を発揮するから
- スタックコンテキストを生成する条件(一例)
position: relative/absoluteかつz-indexがauto以外。position: fixed/sticky。
- スタックコンテキストの仕組み
- スタックコンテキスト内の
z-indexは、その中でのみ評価され、外部には影響しない。
- スタックコンテキスト内の
お読み頂きありがとうございました。