プログラミング
 Computer >> コンピューター >  >> プログラミング >> プログラミング

z-indexが機能しない4つの理由とその解決方法

z-indexとは何でしょうか? z-indexは、HTML要素をレイヤー状に重ねて配置するためのCSSプロパティです。一見とてもシンプルに見えますが、実は落とし穴だらけのプロパティです。

直感に反する奇妙なルールがいくつも存在するため、たとえz-indexに999999という巨大な値を設定しても、思った通りに動いてくれないことがあります。

この記事では、z-indexが期待通りに機能しない最も一般的な4つの理由を詳しく解説します。CSSを使って要素を前面に表示したり、背面へ隠したりする方法を一緒に学んでいきましょう。

1. 同じスタッキングコンテキスト内では、マークアップの出現順に表示される

最初の例として、3つの主要な要素を含む比較的シンプルなレイアウトを見てみましょう。

  • 猫の画像
  • テキスト入りの白いブロック
  • 同じ猫のもう1枚の画像

HTMLマークアップは以下の通りです。

<div class="cat-top"></div>
    
<div class="content__block">
  Meow meow meow...
</div>
    
<div class="cat-bottom"></div>

このレイアウトでは、白いテキストブロックを両方の猫画像より手前に表示したいと考えています。

そのために、両方の猫画像のCSSに負のマージン(ネガティブマージン)を設定し、白いブロックと少し重なるようにしてみました。

.cat-top { 
    margin-bottom: -110px;
}  

.cat-bottom {    
    float: right;
    margin-top: -120px;
}

しかし、実際には次のように表示されます。

See the Pen Z-index: #1: set position, #2: natural stacking order, #3: CSS properties by Jessica (@thecodercoder) on CodePen.

1匹目の猫は期待通り、白いコンテンツブロックの下に配置されています。ところが、2匹目の猫の画像はブロックの上に重なってしまっています!

なぜこのようなことが起こるのでしょうか?

この挙動の原因は、Webページにおける「自然なスタッキング順序」にあります。このルールは、どの要素が前面に来て、どの要素が背面に回るかを決定しています。

要素にz-indexが設定されていなくても、どれが前面になるのかには一定の法則があるのです。

今回のケースでは、どの要素にもz-indexは設定されていません。そのため、スタッキング順序は出現順によって決まります。このルールによれば、マークアップの後ろに書かれた要素ほど、前に書かれた要素の上に表示されます。

(スタッキング順序のガイドラインについては、Mozilla Developer Networkで詳しく読むことができます。)

猫と白いブロックの例でも、このルールが守られています。だからこそ、1匹目の猫は白いブロックの下になり、白いブロックは2匹目の猫の下になったのです。

さて、スタッキング順序の仕組みは理解できましたが、どうすれば2匹目の猫を白いブロックの下に配置できるのでしょうか?

2つ目の理由を見ていきましょう。

2. 要素にpositionが設定されていない

スタッキング順序を決めるもう一つのルールは、要素にpositionが設定されているかどうかです。

要素にpositionを設定するには、static以外の値(relativeabsoluteなど)を持つCSSのpositionプロパティを追加します。

このルールによれば、positionが設定された要素は、設定されていない要素よりも前面に表示されます。

つまり、白いブロックにposition: relativeを設定し、2つの猫要素はpositionなしのままにしておけば、スタッキング順序において白いブロックが猫より前面に来ます。

実際の表示は以下のようになります。

z-indexが機能しない4つの理由とその解決方法

うまくいきましたね!

次にやりたいのは、transformプロパティを使って下側の猫を上下逆にすることです。そうすれば、両方の猫が白いブロックの下から頭だけを出す形になります。

しかし、ここで新たなz-index関連の混乱が生じます。この問題と解決策については、次のセクションで扱います。

3. opacityやtransformなどのCSSプロパティが、新しいスタッキングコンテキストを作ってしまう

先ほど触れたように、下側の猫を上下逆さまにしたいと思います。そのためにtransform: rotate(180deg)を追加します。

.cat-bottom { 
    float: right;
    margin-top: -120px;
    transform: rotate(180deg);
}

しかしこれにより、下側の猫が再び白いブロックの上に表示されてしまいました!

z-indexが機能しない4つの理由とその解決方法

一体何が起こっているのでしょうか??

頻繁に遭遇する問題ではないかもしれませんが、スタッキング順序にはもう一つの重要な側面があります。transformopacityなどの一部のCSSプロパティは、その要素を独自の新しいスタッキングコンテキストの中に置くのです。

これは、.cat-bottom要素にtransformを追加すると、まるでz-index: 0が設定されているかのような振る舞いをするという意味です。positionもz-indexも一切設定していないのに、です!(W3.orgにはopacityプロパティの動作についての詳細ですがやや難解なドキュメントがあります)

思い出してください。白いブロックにはz-indexを設定せず、position: relativeだけを追加しました。それだけで、position未設定の猫たちより前面に表示させるには十分でした。

しかし.bottom-cat要素は、あたかもz-index: 0で相対配置されているかのように振る舞うため、transformを適用した時点で白いブロックの上に来てしまったのです。

解決策は、少なくとも白いブロックにposition: relativeを設定し、明示的にz-indexを指定することです。さらに安全を期すなら、猫要素にもposition: relativeと低めのz-indexを設定しておきましょう。

.content__block {
    position: relative;
    z-index: 2;
}
.cat-top, .cat-bottom {
    position: relative;
    z-index: 1;
}

私の経験では、この対応だけで基本的なz-indexの問題はほぼすべて解決できます。

それでは最後に、z-indexが機能しない4つ目の理由に移りましょう。こちらは少し複雑で、親要素と子要素が関係してきます。

4. 親要素のz-indexレベルにより、要素が低いスタッキングコンテキストに置かれている

コード例を見てみましょう。

See the Pen Z-index: #4 different stacking contexts by Jessica (@thecodercoder) on CodePen.

こちらは、通常のコンテンツが並ぶシンプルなWebページに、「Send Feedback(フィードバックを送信)」と書かれたピンク色のサイドタブがコンテンツの上に配置されています。

そして、猫の写真をクリックすると、半透明のグレー背景オーバーレイ付きのモーダルウィンドウが開きます。

ところが、モーダルウィンドウが開いている間も、サイドタブがグレーのオーバーレイより上に表示されたままです。本来なら、オーバーレイはサイドタブを含むすべての要素より前面に表示したいところです。

該当する要素のCSSを見てみましょう。

.content {
    position: relative;
    z-index: 1;
}

.modal {
    position: fixed;
    z-index: 100;
}

.side-tab {
    position: fixed;
    z-index: 5;
}

すべての要素にpositionが設定されており、サイドタブはz-indexが5なので、z-index: 1のコンテンツ要素の上に配置されています。

そして、モーダルはz-index: 100なので、本来ならz-index: 5のサイドタブより前面に表示されるはずです。しかし実際には、モーダルのオーバーレイはサイドタブの下になってしまっています。

なぜこんなことが起こるのでしょうか?

ここまでは、positionの有無やマークアップ上の順序といった、スタッキングコンテキストに関わる要因を見てきました。

しかし、スタッキングコンテキストにはもう一つ重要なルールがあります。「子要素は親要素のスタッキングコンテキストに制限される」ということです。

3つの要素をもう少し詳しく見てみましょう。

マークアップは以下の通りです。

<section class="content">            
    <div class="modal"></div>
</section>

<div class="side-tab"></div>

マークアップを見ると、contentとside-tabが兄弟要素であることがわかります。つまり、マークアップ上で同じ階層に存在しています(これはz-indexレベルとは別の概念です)。そしてmodalはcontent要素の子要素です。

modalはcontent要素の中にあるため、そのz-index: 100は親であるcontent要素の内部でのみ有効です。例えば、modalと兄弟関係にある他の子要素があれば、それらとの間でz-indexの値に応じて前後関係が決まります。

しかし、それらの子要素のz-index値は、親の外側では何の意味も持ちません。親であるcontent要素のz-indexが1に設定されているからです。

したがって、modalを含む子要素は、そのz-indexレベルから抜け出すことができません。

(ちょっと切ない比喩で覚えるなら、「子どもは親の制約を受け、そこから自由になることはできない」ということです。)

この問題にはいくつかの解決策があります。

解決策:モーダルをcontent親要素の外に移動し、ページのメインのスタッキングコンテキストに置く

修正後のマークアップは以下のようになります。

<section class="content"></section>

<div class="modal"></div>

<div class="side-tab"></div>

これでmodal要素は他の2つと兄弟関係になりました。3つの要素すべてが同じスタッキングコンテキストに置かれるため、それぞれのz-indexレベルが互いに影響し合うようになります。

この新しいスタッキングコンテキストでは、要素は上から順に以下の順序で表示されます。

  • modal(z-index: 100
  • side tab(z-index: 5
  • content(z-index: 1

代替案:content要素からposition設定を外し、modalのz-indexを制限させない

マークアップを変更したくない、あるいは変更できない場合は、content要素からposition設定を削除することでこの問題を解決できます。

.content {
    // positionは未設定    
}

.modal {
    position: absolute;
    z-index: 100;
}

.side-tab {
    position: absolute;
    z-index: 5;
}

content要素が非positionedになったことで、modalのz-index値を制限しなくなります。そのため、開いたモーダルはz-index: 100という高い値のおかげで、サイドタブ要素より前面に表示されます。

ただ、この方法でも一応機能はしますが、個人的には最初の解決策をおすすめします。

なぜなら、将来的に何らかの理由でcontent要素にpositionを設定する必要が出てきた場合、再びmodalのスタッキング順序が制限されてしまうからです。

まとめ

このチュートリアルがお役に立てば幸いです。まとめると、z-indexの問題のほとんどは、以下の2つのガイドラインに従うことで解決できます。

  1. 各要素にpositionが設定されており、z-indexの数値が正しい順序になっていることを確認する。
  2. 親要素が子要素のz-indexレベルを制限していないか確認する。

参考リソース:

  • W3.org: Transparency: the ‘opacity’ property
  • W3.org: Specifying the stack level
  • Mozilla Developer Network: The Stacking Context
  • PhilipWalton.com: What No One Told You About Z-index
  • Smashing Magazine: The Z-index CSS Property
  1. PCでDS4Windowsが動作しないときの対処法を徹底解説

    DS4WindowsがPCで動作しないときの対処法PlayStation 4用の「DualShock 4」コントローラーをPCに接続して使いたい場合、無料のオープンソースアプリ「DS4Windows」を利用すれば簡単に実現できます。しかし、「DS4コントローラーがPCに接続されない」「DS4Windowsが起動しても動かない」といったトラブルは世界的に多く報告されています。幸い、これらの問題の大半は、PC側の設定見直しやドライバーの更新で解決可能です。本記事では、DS4Windowsが動作しないときに試せる対処法を順番にご紹介します。あわせて読みたい:PlayStation本体なしでPS3/P

  2. 「重大なエラー:スタート メニューが機能していません」を解決する6つの対処法

    Windowsパソコンにおいて、スタートメニューは最も重要な要素の一つです。インストール済みのすべてのアプリケーションへ素早くアクセスできる便利な機能ですが、Windowsの他の機能と同様に、不具合が発生することもあります。スタートメニューに重大なエラーが発生すると、メニュー自体が使用できなくなってしまうことがあります。このような問題に直面した場合は、以下の対処法を試してみてください。 「重大なエラー:スタート メニューが機能していません」を修正する方法 1. Windowsエクスプローラーのプロセスを再起動する システムファイルの閲覧やアプリの起動には、Windowsエクスプローラーが不可欠