【CSS】z-indexが効かない!スタックコンテキストの仕組みを解説!

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が効かない例

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のページに詳しく記載されています。

MDN web Docs | 重ね合わせコンテキスト (Stacking context)

補足

  • スタックコンテキストは「スタッキングコンテキスト」や「重ね合わせコンテキスト」や「スタック文脈」とも言います。
  • .div-1, .div-2, .div-2-1, .div-2-2, .div-3はすべて新しいスタックコンテキストを生成しています。

z-indexとスタックコンテキストの関係

z-indexは要素の重なり順を制御するプロパティですが、その要素が所属するスタックコンテキストの中でのみ有効です。冒頭に示したサンプルコードを表に示すと以下のようになります。

クラス名z-index所属するスタックコンテキスト重なり順のイメージ
.div-11html(ルートスタックコンテキスト)root > 1
.div-22html(ルートスタックコンテキスト)root > 2
.div-2-121.div-2(新しいスタックコンテキスト)root > 2 > 21
.div-2-222.div-2(新しいスタックコンテキスト)root > 2 > 22
.div-33html(ルートスタックコンテキスト)root > 3

.div-2-1.div-2-2z-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-indexauto以外。
    • position: fixed/sticky
  • スタックコンテキストの仕組み
    • スタックコンテキスト内のz-indexは、その中でのみ評価され、外部には影響しない。

お読み頂きありがとうございました。