z-indexが効かない原因と解決方法|重なり順・親要素・position等の解説

キーボードの配列

CSSで要素の重なり順を調整したいときに使うのがz-indexです。

ところが、実際に指定してみると、

  • z-index: 9999;にしているのに前面に出ない
  • ヘッダーよりモーダルが後ろに隠れる
  • ドロップダウンメニューが画像やスライダーの下に潜る
  • position: fixed;なのに期待通り重ならない

ということがあります。

「数字を大きくすれば前に出るはず」と思いがちですが、z-indexは単純な数字勝負ではありません。重要なのは、どの要素同士が同じ重なり順のグループにいるのかです。

この記事では、CSSのz-indexが効かない原因と、実際に確認すべきポイント、よくある修正例をわかりやすく解説します。

z-indexとは

z-indexは、要素の重なり順を指定するCSSプロパティです。

横方向をX軸、縦方向をY軸とすると、画面の手前・奥にあたる方向がZ軸です。z-indexは、このZ軸方向の表示順を調整するために使います。基本的には、値が大きい要素ほど前面に表示されます。

.box-a {
  position: relative;
  z-index: 1;
}

.box-b {
  position: relative;
  z-index: 10;
}

この場合、同じ条件であれば.box-bの方が前面に表示されます。

ただし、ここで大切なのが「同じ条件であれば」という部分です。実際には、親要素やposition、transform、opacityなどの影響で、単純に数字を大きくしても前面に出ないことがあります。

z-indexが効かない主な原因

z-indexが効かない場合、よくある原因は次の通りです。

  • positionが指定されていない
  • 親要素の重なり順に閉じ込められている
  • 別のstacking contextが作られている
  • transformやopacityが影響している
  • position: fixed;が親要素の影響を受けている
  • HTMLの配置順や親子関係が想定と違っている

順番に見ていきます。

原因1:positionが指定されていない

まず基本として、z-indexはすべての要素に常に効くわけではありません。多くの場合、次のようなposition指定と一緒に使います。

  • position: relative;
  • position: absolute;
  • position: fixed;
  • position: sticky;

たとえば、以下のようにz-indexだけ指定しても、期待通りに効かないことがあります。

.menu {
  z-index: 100;
}

この場合は、次のようにpositionを追加します。

.menu {
  position: relative;
  z-index: 100;
}

ヘッダーやドロップダウン、ボタンなどでz-indexが効かない場合は、まずpositionが指定されているか確認しましょう。

原因2:親要素のz-indexに閉じ込められている

z-indexで特にハマりやすいのが、親要素の影響です。子要素にどれだけ大きなz-indexを指定しても、親要素が低い重なり順のグループに入っていると、別の親要素の上には出られないことがあります。

たとえば、次のような構造です。

<div class="area-a">
  <div class="modal">モーダル</div>
</div>

<div class="area-b">
  <div class="header">ヘッダー</div>
</div>

CSSが以下のようになっていたとします。

.area-a {
  position: relative;
  z-index: 1;
}

.area-b {
  position: relative;
  z-index: 10;
}

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

この場合、.modalにz-index: 9999;を指定していても、親の.area-aがz-index: 1;なので、.area-bより前に出られないことがあります。数字だけ見ると9999の方が強そうですが、実際には親要素の階層が影響します。

原因3:stacking contextが作られている

z-indexを理解するうえで重要なのが、stacking contexです。stacking contextは、簡単に言うと「重なり順を管理する独立したグループ」tのようなものです。

同じグループ内ではz-indexで重なり順を比較できます。しかし、別のグループに入っている要素同士では、単純に数字だけでは比較できません。stacking contextは、たとえば次のような条件で作られます。

  • positionが指定され、z-indexがauto以外
  • opacityが1未満
  • transformが指定されている
  • filterが指定されている
  • isolation: isolate;が指定されている
  • will-changeが指定されている

特に最近のサイトでは、アニメーションやスライダー、画像効果でtransformが使われることが多いため、意図せずstacking contextが作られているケースがあります。

原因4:transformが親要素に指定されている

意外と多いのが、親要素にtransformが指定されているケースです。

.wrapper {
  transform: translateZ(0);
}

.fixed-menu {
  position: fixed;
  z-index: 9999;
}

このような場合、position: fixed;の要素がビューポート基準ではなく、親要素の影響を受けることがあります。アニメーションやスライダーのために、親要素へtransformが指定されていないか確認しましょう。

原因5:opacityやfilterが影響している

opacity: 0.99;やfilterを指定している場合も、stacking contextが作られることがあります。

.card {
  opacity: 0.99;
}

見た目にはほとんど透明度が変わっていなくても、CSSの重なり順には影響する場合があります。画像のフェード演出、ホバーエフェクト、ぼかし処理などを使っている場合は、opacityやfilterも確認してください。

よくある修正例

ヘッダーを常に前面に出したい場合

固定ヘッダーを前面に出したい場合は、次のように指定します。

.site-header {
  position: sticky;
  top: 0;
  z-index: 1000;
  background: #fff;
}

position: sticky;を使えば、JavaScriptを使わずにスクロール追従ヘッダーを作れる場合があります。ただし、親要素にoverflow: hidden;などがあると、stickyが期待通りに動かないことがあるので注意してください。

モーダルを前面に出したい場合

モーダルは、できるだけbody直下に近い場所へ配置すると管理しやすくなります。

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(0, 0, 0, 0.6);
}

.modal-content {
  position: relative;
  z-index: 10000;
}

親要素の中に深く入れすぎると、親のstacking contextに影響されることがあります。

ドロップダウンメニューが隠れる場合

ドロップダウンが画像やメインビジュアルの下に隠れる場合は、メニュー側と周辺要素の両方を確認します。

.global-nav {
  position: relative;
  z-index: 1000;
}

.dropdown {
  position: absolute;
  z-index: 1001;
}

さらに、メインビジュアルやスライダー側にz-indexやtransformが指定されていないかも確認しましょう。

z-indexが効かない時の確認手順

原因が分からない場合は、次の順番で確認すると切り分けしやすいです。

  1. 対象要素にpositionが指定されているか確認する
  2. 対象要素のz-indexが適用されているか確認する
  3. 親要素にz-indexが指定されていないか確認する
  4. 親要素や祖先要素にtransformがないか確認する
  5. opacity、filter、isolationの指定を確認する
  6. 開発者ツールで実際のCSS適用状況を確認する
  7. HTML構造を見直し、必要なら要素の配置場所を変更する

いきなりz-index: 999999;のような極端な数値を指定するより、まずは構造を確認した方が解決しやすいです。

参考:MDN:重ね合わせコンテキスト

まとめ

z-indexが効かない原因は、単に数値が小さいからとは限りません。重要なのは、次のポイントです。

  • z-indexはposition指定とセットで考える
  • 親要素の重なり順に影響される
  • stacking contextが作られると別グループになる
  • transformやopacityが原因になることがある
  • モーダルやヘッダーはHTML構造も含めて見直す

z-indexは数字を大きくすれば解決する、という単純なものではありません。前面に出したい要素だけでなく、その親要素や周辺要素のCSSも確認することが大切です。