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プロパティです。数値が大きいほど手前に表示されます。
基本的な構文
- .element {
- position: relative; /* positionの指定が必須 */
- z-index: 10; /* 数値が大きいほど手前 */
- }
注意:z-indexは単独では機能しません。必ずpositionプロパティとセットで使います。
指定できるpositionの値
relative(相対位置)absolute(絶対位置)fixed(固定位置)sticky(粘着位置)
position: static;(初期値)ではz-indexは一切効きません。これが最も多い原因です。
原因1:positionプロパティが設定されていない
問題のあるコード例
- .box1 {
- z-index: 10; /* これだけでは効かない! */
- background-color: lightblue;
- }
- .box2 {
- z-index: 5;
- background-color: lightcoral;
- }
上記のコードでは、positionが初期値のstaticのままなので、z-indexは無視されます。
改善後のコード
- .box1 {
- position: relative; /* 追加 */
- z-index: 10;
- background-color: lightblue;
- }
- .box2 {
- position: relative; /* 追加 */
- z-index: 5;
- background-color: lightcoral;
- }
解決ポイント:レイアウトを崩したくない場合はposition: relative;を使うのがおすすめです。要素の位置は変わらず、z-indexだけが有効になります。
原因2:親要素のz-indexが小さい
子要素のz-indexは、親要素のスタッキングコンテキスト内でしか効果がありません。親要素のz-indexが小さいと、子要素がどんなに大きな値でも他の要素の下に隠れてしまいます。
問題のあるコード例
- <div class="parent1">
- <div class="child1">子要素1</div>
- </div>
- <div class="parent2">
- <div class="child2">子要素2</div>
- </div>
- .parent1 {
- position: relative;
- z-index: 1; /* 親のz-indexが小さい */
- }
- .child1 {
- position: relative;
- z-index: 9999; /* いくら大きくしても効かない! */
- }
- .parent2 {
- position: relative;
- z-index: 10;
- }
- .child2 {
- position: relative;
- z-index: 1;
- }
この場合、child1のz-indexが9999でも、親のparent1のz-index(1)がparent2(10)より小さいため、child2の方が前面に表示されます。
改善後のコード
- .parent1 {
- position: relative;
- z-index: 100; /* 親のz-indexを調整 */
- }
- .child1 {
- position: relative;
- z-index: 10;
- }
解決ポイント:親要素のz-indexを調整するか、モーダルなど最前面に表示したい要素は親要素の外(bodyの直下など)に配置しましょう。
原因3:スタッキングコンテキストの理解不足
スタッキングコンテキストとは、z-indexが機能する「階層の範囲」のことです。新しいスタッキングコンテキストが作られると、その中のz-indexは外部の要素と直接比較できなくなります。
スタッキングコンテキストが作られる条件
- positionが
relative、absolute、fixed、stickyで、かつz-indexがauto以外 opacityが1未満transform、filter、perspectiveなどが指定されているwill-changeで特定のプロパティが指定されている
問題のあるコード例
- .modal-overlay {
- position: fixed;
- z-index: 1000;
- opacity: 0.8; /* 新しいコンテキストを作成 */
- }
- .header {
- position: relative;
- z-index: 100;
- transform: translateZ(0); /* これが原因でモーダルの下になることも */
- }
改善後のコード
- .modal-overlay {
- position: fixed;
- z-index: 1000;
- background-color: rgba(0, 0, 0, 0.8); /* opacityの代わりにrgbaを使用 */
- }
- .header {
- position: relative;
- z-index: 100;
- /* transformを削除 */
- }
解決ポイント:不要なスタッキングコンテキストを作らないように、opacityやtransformの使用を見直しましょう。透明度が必要ならrgba()を使います。
原因4:opacityやtransformが親要素に指定されている
前述のとおり、親要素にopacityやtransformが指定されていると、新しいスタッキングコンテキストが作られます。これにより、子要素のz-indexが意図通りに働かなくなります。
実例:ドロップダウンメニューが隠れる
- <div class="nav">
- <button class="nav-button">メニュー</button>
- <div class="dropdown">ドロップダウン内容</div>
- </div>
- .nav {
- position: relative;
- opacity: 0.95; /* これが問題 */
- }
- .dropdown {
- position: absolute;
- z-index: 9999; /* 効かない */
- }
改善方法1:opacityを削除
- .nav {
- position: relative;
- /* opacityを削除 */
- }
改善方法2:ドロップダウンをbodyの直下に配置
- <div class="nav">
- <button class="nav-button">メニュー</button>
- </div>
- <!-- bodyの直下に配置 -->
- <div class="dropdown">ドロップダウン内容</div>
- .dropdown {
- position: fixed; /* fixedに変更 */
- z-index: 1000;
- top: 50px;
- left: 10px;
- }
解決ポイント:モーダルやドロップダウンなど、最前面に表示したい要素はposition: fixed;でbodyの直下に配置するのが確実です。
原因5:z-indexの値が他の要素より小さい
シンプルですが意外と見落としがちなのが、他の要素に設定されているz-indexの値との比較です。
確認方法
Chrome DevToolsで要素を検証し、Computed(計算済み)タブでz-indexの値を確認しましょう。
- 右クリック → 「検証」を選択
- Elementsタブで該当要素を選択
- 右側のComputedタブを開く
- z-indexの値を確認
同じ階層の要素同士でz-indexを比較し、前面に表示したい要素の値を大きくします。
推奨されるz-indexの値の付け方
| 要素の種類 | 推奨z-index |
|---|---|
| 通常の要素 | 1〜10 |
| ドロップダウンメニュー | 100〜500 |
| 固定ヘッダー/フッター | 500〜1000 |
| モーダル背景 | 1000〜5000 |
| モーダルコンテンツ | 5000〜10000 |
注意:z-indexに極端に大きな値(99999など)を指定するのは避けましょう。管理が困難になります。
実践例:モーダルを正しく表示する完全なコード
ここまでの解決方法を踏まえて、モーダルを確実に前面表示するコード例を紹介します。
HTML
- <body>
- <header class="header">ヘッダー</header>
- <main>
- <button class="open-modal">モーダルを開く</button>
- </main>
- <!-- モーダルはbodyの直下に配置 -->
- <div class="modal-overlay">
- <div class="modal-content">
- <h2>モーダルタイトル</h2>
- <p>モーダルの内容</p>
- <button class="close-modal">閉じる</button>
- </div>
- </div>
- </body>
CSS
- .header {
- position: fixed;
- top: 0;
- width: 100%;
- z-index: 100; /* ヘッダーのz-index */
- background-color: #fff;
- }
- .modal-overlay {
- position: fixed; /* fixedで画面全体に固定 */
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(0, 0, 0, 0.7); /* rgbaで透明度 */
- z-index: 1000; /* ヘッダーより大きい値 */
- display: none; /* 初期状態は非表示 */
- justify-content: center;
- align-items: center;
- }
- .modal-overlay.is-open {
- display: flex; /* 表示時 */
- }
- .modal-content {
- position: relative;
- z-index: 1001; /* overlayより大きい値 */
- background-color: #fff;
- padding: 30px;
- border-radius: 8px;
- max-width: 500px;
- }
JavaScript(参考)
- const openBtn = document.querySelector('.open-modal');
- const closeBtn = document.querySelector('.close-modal');
- const modal = document.querySelector('.modal-overlay');
- openBtn.addEventListener('click', () => {
- modal.classList.add('is-open');
- });
- closeBtn.addEventListener('click', () => {
- modal.classList.remove('is-open');
- });
このコードのポイント:
- モーダルを
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は完全に無視されます。必ずrelative、absolute、fixed、stickyのいずれかを指定してください。
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の挙動を理解し、思い通りに要素の重なり順を制御できるようになります。




