z-index が効かないときに確認すること
更新日:2026-08-02
HTML / CSS を勉強していると、かなりの頻度で遭遇するのが、
z-index が効かない…
問題です。
例えば、
- モーダルが前に来ない
- メニューが画像の後ろに隠れる
- ヘッダーが重なり負けする
- position: fixed が埋もれる
などです。
初心者の頃は、
z-index: 999999;
みたいな数字を増やし始めます。
しかし実際には、
数字だけの問題ではない
ケースがかなり多いです。
今回は、
z-index が効かないときに確認すること
を整理していきます。
今回使用するファイル構成
この回では、次のファイルを使用します。
html-practice/
├── index.html
└── css/
└── style.css
まず z-index とは?
z-index は、
前後の重なり順
を決めるCSSです。
数字が大きいほど前に表示されます。
例
<div class="red"></div>
<div class="blue"></div>
.red {
position: absolute;
z-index: 1;
width: 200px;
height: 200px;
background: red;
}
.blue {
position: absolute;
top: 50px;
left: 50px;
z-index: 2;
width: 200px;
height: 200px;
background: blue;
}
この場合、
blue のほうが前
になります。
しかし z-index は罠が多い
初心者がハマりやすい理由は、
z-index だけでは動かない
からです。
1. position が必要
かなり重要です。
NG例
.box {
z-index: 999;
}
これだけでは効かないことがあります。
OK例
.box {
position: relative;
z-index: 999;
}
なぜ?
z-index は基本的に、
position が設定された要素
で動作します。
よく使われるのは、
position: relative;
position: absolute;
position: fixed;
です。
2. スタッキングコンテキストを理解する
ここが z-index 最大の難所です。
ただし初心者のうちは、
重なり専用のグループ
と思うとかなり理解しやすいです。
例えばこういうHTML
<div class="group-a">
<div class="red"></div>
</div>
<div class="group-b">
<div class="blue"></div>
</div>
CSS
.group-a {
position: relative;
z-index: 1;
}
.group-b {
position: relative;
z-index: 2;
}
.red {
position: relative;
z-index: 9999;
}
.blue {
position: relative;
z-index: 1;
}
どっちが前?
初心者は普通、
9999 の red が前!
と思います。
しかし実際には、
blue が前
になります。
なぜ?
理由は、
red は group-a の中blue は group-b の中
だからです。
つまり、
子同士ではなく親グループ同士で勝負している
のです。
イメージするとこう
group-a (z-index:1)└ red (z-index:9999)group-b (z-index:2)└ blue (z-index:1)
この場合、
まず比較されるのは、
group-a vs group-b
です。
結果、
group-b のほうが前
になります。
だから、
group-b の子供達
が全部前へ出ます。
超重要ポイント
子要素は、
親グループの外では戦えない
です。
これが z-index 最大の罠です。
3. transform が原因
かなりよくあります。
例
.parent {
transform: translateX(0);
}
これだけで、
新しい重なりグループ
が作られます。
つまり、
突然「別世界」
になるのです。
よくある事故
モーダル
モーダル z-index:999999
なのに前に出ない。
原因
親にこれがある。
transform: translateY(0);
つまり
モーダルが、
transform親の世界
へ閉じ込められているのです。
だから、
外側のヘッダー
に負けたりします。
4. overflow: hidden
これもかなり多いです。
例
.parent {
overflow: hidden;
}
すると、
はみ出した部分
が切られます。
よくあるケース
ドロップダウンメニューツールチップモーダル
など。
5. fixed が効かない問題
これも初心者がハマります。
原因
親に transform があると、
position: fixed;
の基準がおかしくなることがあります。
よくある症状
fixed のはずなのに画面固定されない
です。
6. 数字を増やしても解決しない
重要です。
よくある状態
z-index: 999999999;
それでも負ける。
なぜ?
z-index は、
別グループ同士
だと比較されないからです。
学校のクラスで例えると
かなりイメージしやすいです
A組
田中(9999点)
B組
佐藤(1点)
でも学校ルール
B組のほうが優先
なら、
田中9999点でも負ける
みたいな感じです。
つまり z-index は
世界が同じなら比較できる
です。
スタッキングコンテキストを作るもの
よく遭遇するのはこれです。
position + z-index
transform
opacity
filter
特に、
transform
が本当に多いです。
Chrome DevTools を使おう
実務ではかなり重要です。
確認ポイント
F12 を押して、
Elements
を開きます。
見る場所
positionz-indexoverflowtransform
を確認します。
実務で多い原因ランキング
かなりリアルです
| 原因 | 多さ |
|---|---|
| position忘れ | 超多い |
| transform | 超多い |
| overflow:hidden | 多い |
| 親z-index | 多い |
| opacity/filter | 中くらい |
実際の現場では?
現場では、
z-index を適当に増やす
のは危険視されます。
なぜなら、
あとで管理不能になる
からです。
よくある運用
例えば、
| 用途 | z-index |
|---|---|
| 通常要素 | 1 |
| ヘッダー | 100 |
| メニュー | 500 |
| モーダル | 1000 |
| ローディング | 9999 |
みたいに、
ルール化
することがあります。
困ったら確認する順番
かなり重要です
① position がある?
position: relative;
など。
② 親に transform ない?
かなり多い。
③ overflow:hidden ない?
切られてない?
④ 別グループになってない?
スタッキングコンテキスト問題。
⑤ DevTools で確認
最終兵器です。
まとめ
z-index が効かない原因は、
数字不足
ではないケースが多いです。
本当に重要なのは、
重なりのルール
を理解することです。
特に、
positiontransformoverflow
は超重要です。
最初はかなり混乱しますが、
「あ、また transform か」
となっていきます