Tips
z-indexが効かない原因、99%はこの2つ
2026-01-30
結論:原因は2つしかない
- positionが指定されていない
- 親のstacking contextに閉じ込められている
z-indexを999にしても効かないのは、この2つのどちらか。
まず確認:positionはあるか
z-indexはpositionがないと効かない。
/* 効かない */
.box {
z-index: 100;
}
/* 効く */
.box {
position: relative;
z-index: 100;
}
static以外(relative、absolute、fixed、sticky)ならOK。
確認方法
- DevToolsで対象要素を選択
- Computedタブを開く
positionを検索staticならz-indexは無効
relativeを付けるだけで解決するケースが大半。
次に確認:stacking contextの罠
positionがあるのに効かない場合、親要素がstacking contextを作っている。
<div class="parent" style="position: relative; z-index: 1;">
<div class="child" style="position: relative; z-index: 9999;">
← これは親の外には出られない
</div>
</div>
<div class="other" style="position: relative; z-index: 2;">
← こっちが上に来る
</div>
親のz-index: 1が壁になる。子がいくら大きな値を持っても、親の外には出られない。
stacking contextを作るプロパティ
これらが親にあると、子のz-indexは親の中で閉じる。
| プロパティ | 条件 |
|---|---|
z-index | auto以外 + position指定 |
opacity | 1未満 |
transform | none以外 |
filter | none以外 |
will-change | transformやopacityなど |
isolation | isolate |
特にtransformとopacityは見落としやすい。
確認方法
- 対象要素の親を順番に確認
- 上記プロパティがあれば、それがstacking contextの境界
- 必要なら親のz-indexを調整するか、構造を変える
私がやらかした失敗
モーダルが背景より後ろに表示される。z-indexを99999にしても変わらない。
3時間悩んだ結果、親にtransform: translateZ(0)があった。GPU最適化のつもりで入れたコードが原因だった。
/* 親にこれがあった */
.modal-container {
transform: translateZ(0); /* stacking contextが生まれる */
}
削除したら直った。
解決パターン早見表
| 症状 | 原因 | 対処 |
|---|---|---|
| z-indexが完全に効かない | position: static | position: relativeを追加 |
| 特定の要素より上に出られない | 親のstacking context | 親のz-indexを上げる or 構造変更 |
| モーダルが後ろに隠れる | transform/opacityが親にある | 該当プロパティを削除 or モーダルをbody直下に移動 |
body直下に移動する解決策
親のstacking contextを変更できない場合、要素をbody直下に移動する。
// モーダルをbody直下に移動
document.body.appendChild(modalElement);
ReactならcreatePortalを使う。
import { createPortal } from 'react-dom';
function Modal({ children }) {
return createPortal(
<div className="modal">{children}</div>,
document.body
);
}
チェックリスト
□ position: static になっていない?
□ 親にz-index(auto以外)がある?
□ 親にtransformがある?
□ 親にopacity: 1未満がある?
□ 親にfilterがある?
この5つを確認すれば原因は特定できる。
まとめ
- z-indexはposition必須(static以外)
- 親のstacking contextを超えられない
transformやopacityも壁になる- 構造を変えられないならPortalで解決