z-indexを設定しても前に出てこない?
z-indexはCSSプロパティの1つで、要素の重なりの順を指定できます1。
しかし、z-indexのみを要素に設定しても重なり順が変わらないことがあります。
z-indexがどのような状況の場合に重なり順を指定できるのかをみていきます。
z-indexが適用できる条件
z-indexはposition:staticの要素に対しては適用できません。
positionがabsolute,relative,fixed,stickyである要素や、flexアイテム、gridアイテムに対してz-index値が適用できます。
しかし、z-indexの数値が大きいものから順に前面に配置されるかというとそうではありません。
z-indexの値は重ね合わせコンテキストと呼ばれる空間内での順序を設定しているためです。
重ね合わせコンテキスト(Stacking Context)
重ね合わせコンテキスト(Stacking Context)とは、HTML要素の3次元的な重なり順を決定する、概念的な空間のことです。
要素は必ず最も近い祖先の重ね合わせコンテキストに属します。
また、重ね合わせコンテキストを生成した要素は、そのコンテキスト内で最背面に配置されます。
重ね合わせコンテキストが生成される条件はいくつかありますが、その中でも代表的なものとして、positionプロパティの設定があります。
-
positionがabsoluteまたはrelativeでz-indexがauto以外 -
positionがfixedまたはsticky
これらの場合には重ね合わせコンテキストが生成されて、z-indexが適用できますが、position:static(デフォルト値)の場合には、z-indexによる指定ができません。
重ね合わせコンテキストの生成条件
positionの値以外に、以下のような条件でも重ね合わせコンテキストが生成されます(他にもあります)。
-
<html>(ルート要素) -
opacityが1未満 -
transformがnone以外 -
filterがnone以外 -
flexアイテムかgridアイテムでz-indexがauto以外
z-index を大きくしても前に出てこない例
以下のようなケースを考えてみます。
<!DOCTYPE html>
<html>
<head>
<link href="stacking_context.css" rel="stylesheet"/>
</head>
<body>
<div class="div1">div 1</div>
<div class="div2">
div 2
<div class="div3">div3</div>
</div>
</body>
</html>
.div1{
background-color: red;
height: 80px;
width: 240px;
position: absolute;
z-index: 10;
}
.div2{
background-color: yellow;
height: 120px;
width: 280px;
position: absolute;
z-index: 1;
}
.div3{
background-color: blue;
height: 160px;
width: 80px;
position: absolute;
z-index: 10000;
}
画像の赤い領域がdiv1、黄色い領域がdiv2、青い領域がdiv3に対応しています。
div1とdiv2は兄弟要素であり、div3はdiv2の子要素です。
設定しているz-indexは、
-
div1z-index: 10; -
div2z-index: 1; -
div3z-index: 10000;
となっており、単純にz-indexの値を比較すると前面から順にdiv3,div1,div2と表示されるような気がします。
しかし、実際にはdiv1,div3,div2の順で表示されています。
これはz-indexが同一の重ね合わせコンテキスト内で比較される値であるからです。
この例では、重ね合わせコンテキストが4つ生成されています。
html
├── div1
└── div2
└── div3
div1とdiv2はルート要素の生成した重ね合わせコンテキストに属すため、z-index値の比較によってdiv1が前面にきます。
しかし、div3はルート要素の重ね合わせコンテキストには属さないため(div2の生成した重ね合わせコンテキストに属す)、div3とdiv1のどちらが前面にくるかは、div3とdiv1のz-index値ではなく、div3の親要素であるdiv2とdiv1のz-index値の比較で決定されています。
div2とdiv3については、同一の重ね合わせコンテキストに属さないため、z-indexによる比較はされません。
div2のz-index値をdiv3のものより大きくなるように設定した場合でも、div3が前面にきます。
これは、重ね合わせコンテキストを生成した要素は、そのコンテキスト内で最も奥に配置されるためです2。
さいごに
z-indexによって重なり順を指定するためには、position:staticでないことなどの条件があります。
また、条件を満たした場合でも、必ずしもz-indexの大きい順に前面にくるのではなく、重ね合わせコンテキスト同士の前後関係が関わってきます。
なぜか前面にこないという場合には、これらを疑ってみるとよさそうですね。
