z-index は「どのレイヤーが手前に来るか」を決める番号
z-index は、要素の「前後関係(レイヤーの順番)」を数字でコントロールするためのプロパティです。
値が大きいほど手前、小さいほど奥に表示されます。
ただし、単純に「数字が大きければ勝ち」ではなく、
「どの“スタッキングコンテキスト”の中にいるか」で勝負の土俵が変わります。
ここを理解しておくと、z-index でハマることが一気に減ります。
z-index が効く前提条件と「スタッキングコンテキスト」
z-index が効くのは position がある程度指定されている要素
基本的に、z-index が意味を持つのは
position が relative / absolute / fixed / sticky の要素です。
.box {
position: relative;
z-index: 10;
}
CSSposition: static(デフォルト)のまま z-index を指定しても、
ブラウザによっては無視されたり、期待通りに動かなかったりします。
「前後関係を制御したい要素には position を付ける」
これは z-index 設計の前提として覚えておいてください。
スタッキングコンテキストという「レイヤーのグループ」
z-index は、同じ「スタッキングコンテキスト」の中でしか比較されません。
スタッキングコンテキストは、ざっくり言うと「レイヤーのグループ」です。
例えば、次のような要素は新しいスタッキングコンテキストを作ります。
.parent {
position: relative;
z-index: 0; /* 多くのブラウザで新しいコンテキスト */
}
.modal {
position: fixed;
z-index: 50;
}
.dropdown {
position: absolute;
z-index: 20;
}
CSS親ごとに「別のレイヤー世界」ができるイメージです。
その世界の中では z-index の大小で前後が決まりますが、
別の世界同士では「親同士の前後関係」が優先されます。
ここがわかっていないと
「z-index: 9999 にしたのに、まだ隠れるんだけど?」
という沼にハマりがちです。
例1:ヘッダー、ドロップダウン、モーダルのレイヤー設計
全体のレイヤーのイメージ
ヘッダー(固定)
ドロップダウンメニュー
モーダルのオーバーレイと本体
このあたりは、レイヤーの優先順位をあらかじめ決めておくと設計が楽になります。
例えば、こういう優先度にします。
ヘッダーよりモーダルが上
モーダルの中のコンテンツよりオーバーレイが下
ドロップダウンはヘッダーの上
これを z-index に落とし込んでみます。
CSS 版
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 56px;
background: #0f172a;
color: #e5e7eb;
z-index: 20;
}
.header-menu {
position: absolute;
top: 100%;
right: 16px;
background: #ffffff;
border-radius: 8px;
box-shadow: 0 10px 30px rgba(15,23,42,0.25);
z-index: 30;
}
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(15,23,42,0.5);
z-index: 40;
}
.modal {
position: fixed;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
z-index: 50;
}
CSS<header class="header">
ヘッダー
<div class="header-menu">
メニュー
</div>
</header>
<div class="modal-overlay"></div>
<div class="modal">
<div class="modal-content">
モーダル本体
</div>
</div>
HTMLここでは、
ヘッダー 20
ヘッダーメニュー 30
モーダルオーバーレイ 40
モーダル本体 50
というレイヤー構造になっています。
Tailwind 版
Tailwind にはあらかじめ z-index のユーティリティが用意されています。
z-0, z-10, z-20, z-30, z-40, z-50 などです。
<header class="fixed top-0 left-0 right-0 h-14 bg-slate-900 text-slate-100 z-20">
ヘッダー
<div class="absolute top-full right-4 mt-2 bg-white rounded-lg shadow-lg z-30">
メニュー
</div>
</header>
<div class="fixed inset-0 bg-slate-900/50 z-40"></div>
<div class="fixed inset-0 flex items-center justify-center z-50">
<div class="bg-white p-6 rounded-lg w-80">
モーダル本体
</div>
</div>
HTMLTailwind の z-index は「段階的なレイヤー設計」に向いています。
大きな単位で 10, 20, 30… と分けておくと、後から調整しやすくなります。
例2:カードの中で「バッジやオーバーレイ」を前面に出す
CSS 版
.card {
position: relative;
background: #ffffff;
border-radius: 12px;
overflow: hidden;
}
.card-image {
position: relative;
z-index: 0;
}
.card-badge {
position: absolute;
top: 12px;
left: 12px;
background: #ef4444;
color: #ffffff;
padding: 4px 8px;
border-radius: 9999px;
font-size: 12px;
z-index: 10;
}
.card-overlay {
position: absolute;
inset: 0;
background: linear-gradient(to top, rgba(15,23,42,0.7), transparent);
z-index: 5;
}
CSS<div class="card">
<div class="card-image">
<img src="photo.jpg" alt="">
</div>
<div class="card-overlay"></div>
<span class="card-badge">NEW</span>
</div>
HTMLここでは、
画像 0
オーバーレイ 5
バッジ 10
という順番でレイヤーを重ねています。
「どれを一番手前に見せたいか」を数字で表現しているイメージです。
Tailwind 版
<div class="relative bg-white rounded-xl overflow-hidden">
<div class="relative z-0">
<img src="photo.jpg" alt="" class="w-full h-48 object-cover">
</div>
<div class="absolute inset-0 bg-gradient-to-t from-slate-900/70 to-transparent z-10"></div>
<span class="absolute top-3 left-3 bg-red-500 text-white text-xs px-2 py-1 rounded-full z-20">
NEW
</span>
</div>
HTMLTailwind では z-0, z-10, z-20 のように段階を分けておくと、
「どれが一番手前か」が視覚的にもわかりやすくなります。
例3:position と z-index の組み合わせでハマりやすいパターン
親の z-index が子の限界を決めてしまう
例えば、こんな構造を考えます。
.parent-a {
position: relative;
z-index: 10;
}
.parent-b {
position: relative;
z-index: 5;
}
.child-of-b {
position: absolute;
z-index: 9999;
}
CSS<div class="parent-a">
A
</div>
<div class="parent-b">
<div class="child-of-b">
Bの子
</div>
</div>
HTMLこの場合、
どれだけ child-of-b の z-index を大きくしても、parent-a の上には出られません。
理由は、parent-a と parent-b がそれぞれ別のスタッキングコンテキストを作っていて、
その「親同士の z-index の勝負」が先に決まってしまうからです。
このようなときは、
本当に z-index を付けるべきなのは「子」ではなく「親」だと気づけると、設計がスッキリします。
Tailwind での同じ状況
<div class="relative z-10 bg-blue-100 p-4">
A
</div>
<div class="relative z-5 bg-red-100 p-4">
<div class="absolute z-[9999] bg-red-500 text-white p-2">
Bの子
</div>
</div>
HTML見た目としては、
A が常に B の子より手前に来ます。z-[9999] のような大きな値を子に付けても、
親の z-5 の「世界の中」でしか戦えないからです。
Tailwind の z-index 設計の考え方
Tailwind には、デフォルトでいくつかの z-index レベルが用意されています。
z-0, z-10, z-20, z-30, z-40, z-50
これを「レイヤーの階層」としてざっくり決めておくと、設計が楽になります。
例えば、こんな感じのレイヤー設計がよく使われます。
z-0〜z-10
通常のコンテンツ、カード内のオーバーレイなど
z-20
固定ヘッダー、固定フッターバー
z-30
ドロップダウンメニュー、ツールチップ
z-40
モーダルのオーバーレイ
z-50
モーダル本体、最前面に出したい UI
Tailwind では、どうしても中間の値が欲しいときは z-[15] のように任意値も使えますが、
基本は用意されたステップの中で設計した方が、チーム開発では混乱が少ないです。
実務での「z-index 設計」のコツ(ここが一番大事)
z-index は「その場しのぎで数字を盛る」とすぐにカオスになります。
なので、最初にざっくりと「レイヤーのルール」を決めておくのが大事です。
例えば、こんな考え方です。
まず、大きなレイヤーの種類を決める。
ベースコンテンツ
ナビゲーション
ポップアップ系(ドロップダウン、ツールチップ)
モーダル
それぞれに「だいたいこのあたりの z-index を使う」と決めておく。
ベース 0〜10
ナビ 20
ポップアップ 30
モーダル 40〜50
こうしておくと、
「このコンポーネントはどのレイヤーに属するか?」を考えるだけで、
自然と z-index の値が決まっていきます。
そしてもうひとつ大事なのは、
「本当に z-index が必要か?」を毎回疑うことです。
position の指定や HTML の順番、スタッキングコンテキストの整理だけで解決できるなら、
z-index を増やさない方が、長期的にはきれいな設計になります。
まとめ
z-index は
要素の前後関係を数字で制御するためのプロパティで、
position とスタッキングコンテキストとセットで考える必要があります。
CSS では
position: relative;
z-index: 10;
CSSTailwind では
class="relative z-10"
HTMLのように使います。
ヘッダー、ドロップダウン、モーダル、オーバーレイ、ツールチップなど、
「どれを手前に見せたいか」を意識して、
レイヤーごとに z-index の“帯”を決めておくと、
レイアウトがぐっと安定します。

