CSSのz-indexが効かない!原因と5つの解決方法を初心者向けに解説

「z-indexで999を指定したのに、要素が前面に表示されない…」「モーダルが背景の下に隠れてしまう…」

CSS学習中のあなたは、こんな悩みを抱えていませんか?実はz-indexが効かない原因のほとんどは、positionプロパティの設定ミスか、スタッキングコンテキストの理解不足にあります。

この記事で分かること:

  • z-indexが効かない5つの原因と解決方法
  • positionとz-indexの正しい組み合わせ方
  • スタッキングコンテキストの基本概念

初心者の方にも分かるように、コード例を交えながら丁寧に解説していきます。

早く知りたい人向け:z-indexが効かない原因チェックリスト

まずは以下のポイントを確認してください。ほとんどのケースはこれで解決します。

チェック項目 確認内容 対処法
positionが未設定 position: static;(初期値)になっていないか position: relative;を追加
親要素の影響 親要素にz-indexが設定されていないか 親要素のz-indexを調整
スタッキングコンテキスト 別のコンテキスト内の要素ではないか 同じコンテキスト内に配置
opacityやtransform 親要素にopacity 該当プロパティを削除or調整
z-indexの値 他の要素より小さい値になっていないか より大きな数値に変更

z-indexとは?基本的な使い方

z-indexは、要素の重なり順(奥行き方向の表示順序)を制御するCSSプロパティです。数値が大きいほど手前に表示されます。

基本的な構文

  1. .element {
  2. position: relative; /* positionの指定が必須 */
  3. z-index: 10; /* 数値が大きいほど手前 */
  4. }

注意:z-indexは単独では機能しません。必ずpositionプロパティとセットで使います。

指定できるpositionの値

  • relative(相対位置)
  • absolute(絶対位置)
  • fixed(固定位置)
  • sticky(粘着位置)

position: static;(初期値)ではz-indexは一切効きません。これが最も多い原因です。

原因1:positionプロパティが設定されていない

問題のあるコード例

  1. .box1 {
  2. z-index: 10; /* これだけでは効かない! */
  3. background-color: lightblue;
  4. }
  5.  
  6. .box2 {
  7. z-index: 5;
  8. background-color: lightcoral;
  9. }

上記のコードでは、positionが初期値のstaticのままなので、z-indexは無視されます。

改善後のコード

  1. .box1 {
  2. position: relative; /* 追加 */
  3. z-index: 10;
  4. background-color: lightblue;
  5. }
  6.  
  7. .box2 {
  8. position: relative; /* 追加 */
  9. z-index: 5;
  10. background-color: lightcoral;
  11. }

解決ポイント:レイアウトを崩したくない場合はposition: relative;を使うのがおすすめです。要素の位置は変わらず、z-indexだけが有効になります。

原因2:親要素のz-indexが小さい

子要素のz-indexは、親要素のスタッキングコンテキスト内でしか効果がありません。親要素のz-indexが小さいと、子要素がどんなに大きな値でも他の要素の下に隠れてしまいます。

問題のあるコード例

  1. <div class="parent1">
  2. <div class="child1">子要素1</div>
  3. </div>
  4.  
  5. <div class="parent2">
  6. <div class="child2">子要素2</div>
  7. </div>
  1. .parent1 {
  2. position: relative;
  3. z-index: 1; /* 親のz-indexが小さい */
  4. }
  5.  
  6. .child1 {
  7. position: relative;
  8. z-index: 9999; /* いくら大きくしても効かない! */
  9. }
  10.  
  11. .parent2 {
  12. position: relative;
  13. z-index: 10;
  14. }
  15.  
  16. .child2 {
  17. position: relative;
  18. z-index: 1;
  19. }

この場合、child1のz-indexが9999でも、親のparent1のz-index(1)がparent2(10)より小さいため、child2の方が前面に表示されます。

改善後のコード

  1. .parent1 {
  2. position: relative;
  3. z-index: 100; /* 親のz-indexを調整 */
  4. }
  5.  
  6. .child1 {
  7. position: relative;
  8. z-index: 10;
  9. }

解決ポイント:親要素のz-indexを調整するか、モーダルなど最前面に表示したい要素は親要素の外(bodyの直下など)に配置しましょう。

原因3:スタッキングコンテキストの理解不足

スタッキングコンテキストとは、z-indexが機能する「階層の範囲」のことです。新しいスタッキングコンテキストが作られると、その中のz-indexは外部の要素と直接比較できなくなります。

スタッキングコンテキストが作られる条件

  • positionがrelativeabsolutefixedstickyで、かつz-indexがauto以外
  • opacityが1未満
  • transformfilterperspectiveなどが指定されている
  • will-changeで特定のプロパティが指定されている

問題のあるコード例

  1. .modal-overlay {
  2. position: fixed;
  3. z-index: 1000;
  4. opacity: 0.8; /* 新しいコンテキストを作成 */
  5. }
  6.  
  7. .header {
  8. position: relative;
  9. z-index: 100;
  10. transform: translateZ(0); /* これが原因でモーダルの下になることも */
  11. }

改善後のコード

  1. .modal-overlay {
  2. position: fixed;
  3. z-index: 1000;
  4. background-color: rgba(0, 0, 0, 0.8); /* opacityの代わりにrgbaを使用 */
  5. }
  6.  
  7. .header {
  8. position: relative;
  9. z-index: 100;
  10. /* transformを削除 */
  11. }

解決ポイント:不要なスタッキングコンテキストを作らないように、opacitytransformの使用を見直しましょう。透明度が必要ならrgba()を使います。

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

前述のとおり、親要素にopacitytransformが指定されていると、新しいスタッキングコンテキストが作られます。これにより、子要素のz-indexが意図通りに働かなくなります。

実例:ドロップダウンメニューが隠れる

  1. <div class="nav">
  2. <button class="nav-button">メニュー</button>
  3. <div class="dropdown">ドロップダウン内容</div>
  4. </div>
  1. .nav {
  2. position: relative;
  3. opacity: 0.95; /* これが問題 */
  4. }
  5.  
  6. .dropdown {
  7. position: absolute;
  8. z-index: 9999; /* 効かない */
  9. }

改善方法1:opacityを削除

  1. .nav {
  2. position: relative;
  3. /* opacityを削除 */
  4. }

改善方法2:ドロップダウンをbodyの直下に配置

  1. <div class="nav">
  2. <button class="nav-button">メニュー</button>
  3. </div>
  4.  
  5. <!-- bodyの直下に配置 -->
  6. <div class="dropdown">ドロップダウン内容</div>
  1. .dropdown {
  2. position: fixed; /* fixedに変更 */
  3. z-index: 1000;
  4. top: 50px;
  5. left: 10px;
  6. }

解決ポイント:モーダルやドロップダウンなど、最前面に表示したい要素はposition: fixed;でbodyの直下に配置するのが確実です。

原因5:z-indexの値が他の要素より小さい

シンプルですが意外と見落としがちなのが、他の要素に設定されているz-indexの値との比較です。

確認方法

Chrome DevToolsで要素を検証し、Computed(計算済み)タブでz-indexの値を確認しましょう。

  1. 右クリック → 「検証」を選択
  2. Elementsタブで該当要素を選択
  3. 右側のComputedタブを開く
  4. z-indexの値を確認

同じ階層の要素同士でz-indexを比較し、前面に表示したい要素の値を大きくします。

推奨されるz-indexの値の付け方

要素の種類 推奨z-index
通常の要素 1〜10
ドロップダウンメニュー 100〜500
固定ヘッダー/フッター 500〜1000
モーダル背景 1000〜5000
モーダルコンテンツ 5000〜10000

注意:z-indexに極端に大きな値(99999など)を指定するのは避けましょう。管理が困難になります。

実践例:モーダルを正しく表示する完全なコード

ここまでの解決方法を踏まえて、モーダルを確実に前面表示するコード例を紹介します。

HTML

  1. <body>
  2. <header class="header">ヘッダー</header>
  3. <main>
  4. <button class="open-modal">モーダルを開く</button>
  5. </main>
  6. <!-- モーダルはbodyの直下に配置 -->
  7. <div class="modal-overlay">
  8. <div class="modal-content">
  9. <h2>モーダルタイトル</h2>
  10. <p>モーダルの内容</p>
  11. <button class="close-modal">閉じる</button>
  12. </div>
  13. </div>
  14. </body>

CSS

  1. .header {
  2. position: fixed;
  3. top: 0;
  4. width: 100%;
  5. z-index: 100; /* ヘッダーのz-index */
  6. background-color: #fff;
  7. }
  8.  
  9. .modal-overlay {
  10. position: fixed; /* fixedで画面全体に固定 */
  11. top: 0;
  12. left: 0;
  13. width: 100%;
  14. height: 100%;
  15. background-color: rgba(0, 0, 0, 0.7); /* rgbaで透明度 */
  16. z-index: 1000; /* ヘッダーより大きい値 */
  17. display: none; /* 初期状態は非表示 */
  18. justify-content: center;
  19. align-items: center;
  20. }
  21.  
  22. .modal-overlay.is-open {
  23. display: flex; /* 表示時 */
  24. }
  25.  
  26. .modal-content {
  27. position: relative;
  28. z-index: 1001; /* overlayより大きい値 */
  29. background-color: #fff;
  30. padding: 30px;
  31. border-radius: 8px;
  32. max-width: 500px;
  33. }

JavaScript(参考)

  1. const openBtn = document.querySelector('.open-modal');
  2. const closeBtn = document.querySelector('.close-modal');
  3. const modal = document.querySelector('.modal-overlay');
  4.  
  5. openBtn.addEventListener('click', () => {
  6. modal.classList.add('is-open');
  7. });
  8.  
  9. closeBtn.addEventListener('click', () => {
  10. modal.classList.remove('is-open');
  11. });

このコードのポイント:

  • モーダルをposition: fixed;でbodyの直下に配置
  • 背景の透明度はrgba()で指定(opacityを使わない)
  • z-indexをヘッダー(100)より大きい値(1000)に設定
  • モーダルコンテンツは背景よりさらに前面(1001)に配置

よくある質問

z-indexに負の値は使えますか?

使えます。z-index: -1;のように負の値を指定すると、通常の要素より背面に配置されます。ただし、親要素の背景色や背景画像の下に隠れる可能性があるため、使用には注意が必要です。

z-indexの最大値はいくつですか?

理論上は2147483647(2³¹-1)が最大値です。ただし、実用上は1000〜10000程度の値で十分です。極端に大きな値を使うと管理が困難になるため、避けましょう。

position: static;でz-indexを有効にする方法はありますか?

ありません。position: static;(初期値)の場合、z-indexは完全に無視されます。必ずrelativeabsolutefixedstickyのいずれかを指定してください。

flexboxやgridのアイテムでもz-indexは効きますか?

はい、効きます。flexboxやgridのアイテムは、positionがstaticでもz-indexが有効になります。これは特例的な動作です。

z-indexが効かない時、何から確認すべきですか?

まずはpositionプロパティの設定を確認してください。90%以上のケースはこれで解決します。次に親要素のz-index、そしてスタッキングコンテキストの有無をチェックしましょう。

まとめ

z-indexが効かない原因と解決方法を5つ紹介しました。

重要なポイント:

  • z-indexは必ずpositionプロパティとセットで使う(static以外)
  • 親要素のz-indexが小さいと子要素も影響を受ける
  • opacityやtransformは新しいスタッキングコンテキストを作る
  • モーダルなどはposition: fixed;でbodyの直下に配置すると確実
  • z-indexの値は計画的に設定する(極端な値は避ける)

これらのポイントを押さえれば、z-indexの挙動を理解し、思い通りに要素の重なり順を制御できるようになります。

スポンサーリンク
スポンサーリンク