Z-indexスタック文脈 と 重ね合わせコンテキスト
重ね合わせコンテキストは以下のような場面で、文書の随所に様々な要素によって構成されます。
- 文書 (HTML) のルート要素
- position の値が "absolute" 又は "relative" であり、かつ z-index の値が "auto" 以外の要素
- position の値が "fixed" 又は "sticky" の要素 。
- フレックス (flexbox) コンテナーの子であり、 z-index 値が "auto" 以外の要素。
- opacity の値が 1 未満である要素 (不透明度の仕様をご覧ください)。
- mix-blend-mode の値が "normal" 以外の要素
- 以下のプロパティ値が "none" 以外の要素。
- isolation の値が "isolate" である要素。
- -webkit-overflow-scrolling の値が "touch" である要素
- will-change の値が、初期値以外で重ね合わせコンテキストを作成する任意のプロパティを指定している要素 (この記事を参照)。
- contain の値が "layout" 又は "paint" である要素、又はこれらの何れかを含む混合値。
重ね合わせコンテキストの内部で、子要素は前に説明した規則に従って重ね合わせられます。重要なのは、子要素の z-index 値は、その親要素に対してのみ意味を持つということです。重ね合わせコンテキストは、その親の重ね合わせコンテキストでは不可分な一つの固まりとして扱われます。
まとめると、
- 重ね合わせコンテキストは他の重ね合わせコンテキストに含めることができ、その結果重ね合わせコンテキストの階層構造ができます。
- 重ね合わせコンテキストはすべて、その兄弟要素と完全に独立しています。重ね合わせ処理では、子孫要素だけが考慮されます。
- 重ね合わせコンテキストははめ込み式です。要素の中身が重ねられた後、その要素がまるごと、今度は親の重ね合わせコンテキストの重ね合わせ順の中にあるとみなされます。
スタック文脈の例 1
Division Element #1
position: relative;
z-index: 5;
- DIV #1
- DIV #2
- DIV #3
- DIV #4
- DIV #5
- DIV #6
DIV #3 の内側で重なり方が完全に決まる。
先ず は、DIV #3 内部の重ね合わせと描画が行われ、
次に DIV #3 はルート要素に丸ごと 渡され、兄弟要素
との重ね合わせ処理が行われる。
Division Element #2
position: relative;
z-index: 2;
Division Element #4
position: relative;
z-index: 6;
Division Element #3
position: absolute;
z-index: 4;
Division Element #5
position: relative;
z-index: 1;
Division Element #6
position: absolute;
z-index: 3;
スタック文脈の例 2
Division Element #1
position: relative;Division Element #2
position: absolute;z-index: 2;
Division Element #3
position: relative;z-index: 1;
Division Element #4
position: absolute;z-index: 10;
- DIV #1
- DIV #2 ( z-index: 2 )
- DIV #3 ( z-index: 1 )
- DIV #4 ( z-index: 10 )
スタック文脈の例 3
z-index: 1;
z-index: 1;
この例では、複数のレベルを持つ HTML 階層内で、位置指定された要素を組み合わせたときと、z-index がクラスセレクタを使って設定されたとき、起こる問題を示します。
通常この種類のメニューはスクリプトにより生成されます。このためスタイルルールは id セレクタではなく、クラスセレクタで割り当てられます。
もし 3 つのメニュー階層が不充分に重なると、重なりの管理が問題になるかもしれません。
1 レベル目のメニューは relative で位置指定されているだけなので、スタック文脈は作られません。
2 レベル目のメニューは親要素内で absolute で位置指定されています。これを 1 レベル目のすべてのメニューより上に置くために、z-index が使われています。問題は 2 レベル目のメニューそれぞれにスタック文脈が作られることと、3 レベル目のメニューが自分の親要素に属していることです。
したがって 3 レベル目のメニューは後ろにある 2 レベル目のメニューより下に重なりますが、これは 2 レベル目のメニューがすべて同一の z-index 値を持っていて、デフォルトのスタック規則が適用されるからです。
ルートのスタック文脈
- LEVEL #1
- LEVEL #2 (z-index: 1)
- LEVEL #3
- ...
- LEVEL #3
- LEVEL #2 (z-index: 1)
- ...
- LEVEL #2 (z-index: 1)
- liLEVEL #1
- ...
- LEVEL #1
この問題を回避するには、異なるレベル間のメニューの重なりを取り除くか、独自(で異なった)z-index 値を クラスセレクタではなく id セレクタを通じて設定するか、HTML の階層構造をなくします。
スタック文脈 と フロート(float)
DIV #1
position: absolute;
z-index: 1;
DIV #2
float: right;
DIV #3
float: left;
DIV #4
no positioning
position: absolute;
フロートブロックでは、積み重ね順が少し違います。フロートブロックは位置指定されていないブロックとされているブロックの間に置かれます:
1 ルート要素の背景とボーダー
2 通常フローに乗る子孫要素。HTML 内の出現順
3 浮遊ブロック
4 位置指定された子孫要素。HTML 内の出現順
位置指定されないブロック (DIV #4) の背景とボーダーは、浮遊ブロックから影響を受けません。一方で、その内容は影響を受けます。これは CSS 標準のフロートの動作によるものです。