z-indexが効かない!?そんな時はスタックコンテキストに注目してみよう!

はじめまして。2024年新卒入社予定のガッシュです。現在は内定者アルバイトとして働かせて頂いております。

アルバイト

ガッシュ

 

今回の記事では、僕が学習を始めて間もないころに苦戦した『z-indexとスタックコンテキスト』についてピックアップしました。

(嫌な記憶を呼び起こしながら・・・)

それでは本題に入ります!
CSSにおいて、z-indexの値で要素の重ね順を操作すると思いますが、
スタックコンテキストの罠にかかると、うまく制御できない事態に陥ってしまいます。

そもそもスタックコンテキストとは?

重ね合わせコンテキスト (Stacking context) は、ビューポートまたはウェブページに面していると想定されるユーザーに対する仮想的な Z 軸に沿って並べられた HTML 要素の三次元の概念化です。 HTML 要素は、要素の属性に基づいてこの空間を優先度つきの順序で占有します。

引用:MDN web Docs | 重ね合わせコンテキスト

・・・・・

難しいと思うので、実際にコードに触れながら体感していきましょう。
(つまづいた時は遊び感覚でコードを書いてみることをおすすめします)

 

例えば、順に要素を重ねたい場合、以下のようなコードになると思います。

See the Pen Untitled by 金光洙 (@wwehgkun-the-looper) on CodePen.

 

このようにz-indexの値が大きい要素ほど前面に表示されます。

ここまではpostionz-indexの基本的な操作です。

それでは、div-1の要素内にさらに要素を重ねたいため、div-1下に要素を追加するとします。

 

See the Pen Untitled by 金光洙 (@wwehgkun-the-looper) on CodePen.

 

するとこのように、親要素であるdiv-1は最背面に配置されているにも関わらず、その子要素div-A、div-Bは最前面に配置されてしまいます。

 

誤った指摘として、div-A、div-Bのz-indexを下げれば(もしくはdiv-2、div-3のz-indexを上げれば)修正できるというものがあります。しかしそれでは、根本的な解決にはなりません。

 

ここでの問題は、スタックコンテキストがうまく生成できていないからです!

 

スタックコンテキストとは、いわば要素がz-indexで争うためのフィールドのようなものです。
そしてそのフィールドは、初期状態ではhtml要素が生成しているルートスタックコンテキストを参照しています。つまり、初期状態ではhtml全域がフィールドであることを意味します。

 

その結果、階層が下にあっても、ルートスタックコンテキストではz-indexの値が相対的に大きいため、前面に配置されてしまいます。

 

したがって、新たにフィールドを用意し、div-A、div-Bがそのフィールド内でのみ争うようにしてあげなければなりません。

スタックコンテキストを生成する条件

以上に続き、今回そのフィールド(スタックコンテキスト)を生成するには、以下2つの条件を揃える必要があります。

  1. positionstatic以外の値を指定する
  2. z-indexauto(デフォルト値)以外の値を指定する

今回フィールドとしての役割を持ってほしいのは、div-A、div-Bの親要素であるdiv-1であるため、
div-1を条件に当てはまるように書き直す必要があります。

 

See the Pen Untitled by 金光洙 (@wwehgkun-the-looper) on CodePen.

 

条件1はすでに満たしているため、条件2のz-indexを指定します。

 

するとdiv-A、div-Bは、div-1が生成したスタックコンテキスト内でのみ争うようになるため、
z-indexの値が高いからと言って、div-2、div-3を超えることはありません。

 

その他にもスタックコンテキストを生成する要素はいくつか存在しますが、まずはスタックコンテキストの存在を知ってもらえればと思います!

まとめ

改めて、今回紹介したスタックコンテキストは、CSSを学習するうえで序盤にぶち当たる壁だと思います。

(僕も理解に1日かかりました…)

  • z-indexとスタックコンテキストの関係性を知る
  • 基礎でもしっかり概念を抑えることの重要さ

今回の記事では以上のことをお伝えできればと思います!

最後に

ロジカルスタジオでは、エンジニアを募集中です!

ぜひ下のバナーから確認してみて下さい!