CSSのz-indexを大きくしても前に出ない|親要素の重なりと見切れの確認手順

CSSのz-indexが前に出ないときに、親の重なりと見切れを確認する

z-index: 9999;にしても、画像のラベルやメニューが手前に出ない。値をさらに大きくする前に、隠れ方を確認してみましょう。

z-indexは、ページ全体の要素を一つの順位表に並べる指定ではありません。値が効く条件に加え、親要素が作る重なりのグループや、はみ出した部分を切る設定が表示を左右します。

この記事では、カードに付けた「NEW」ラベルを例に、確認する要素と直す場所を分けて説明します。まず症状に近い項目を選び、直ったら最後の表示確認へ進めば大丈夫です。

目次

まず「後ろに隠れる」と「親の端で切れる」を見分ける

最初に、見えない部分がどこから始まっているかを見ます。次の表は原因を絞るための目安です。複数の設定が同時に影響している場合もあります。

見え方・条件最初に見る場所確認すること
値を変えても重なりが変わらない前に出したい要素自身position、Flex/Gridの子か、値が有効か
別のカードやヘッダーの後ろに隠れる両方の要素の親をたどる重なりのグループと、その親同士の順序
親の四角や角丸に沿って途中で切れる切れている境界を持つ親overflowやclip-pathなどの切り取り

重なり順の変更と、切り取りの解除は別の修正です。 親の外へ描画できない状態では、子のz-indexを大きくしても欠けた部分は戻りません。

z-indexが効く対象と値になっているか確認する

通常の要素はpositionと整数の指定を確認する

通常の要素でz-indexを使うときは、positionがrelative、absolute、fixed、stickyのいずれかになっているかを確認します。初期値のstaticでは、後述するFlex/Gridのアイテムを除き、z-indexを指定しても重なり順を変えられません。

たとえば、今ある場所を基準にラベルの重なりだけを調整するなら、ラベルのCSSに次の指定を加えます。

.card__badge {
  position: relative;
  z-index: 1;
}

relativeだけなら、topなどでずらさない限り、元の位置にとどまります。一方、すでにabsoluteで配置しているラベルをrelativeへ変える必要はありません。重なりの修正のために、配置方法まで一律に変えないようにします。

z-indexの数値には単位を付けません。z-index: 10;は有効ですが、z-index: 10px;やz-index: 1.5;は無効です。初期値のautoと整数の0も同じ意味ではなく、relative・absoluteの要素では、整数を指定すると独立した重なりのグループを作ります。

配置の基準自体が分からない場合は、positionのrelative・absolute・fixed・stickyの違いを先に確認してください。値の定義はMDNのz-indexの説明でも確認できます。

Flex/Gridでは「直接の子」にもz-indexが効く

親がdisplay: flex;またはdisplay: grid;のとき、レイアウトに並ぶ直接の子は、それぞれFlexアイテム・Gridアイテムになります。これらのアイテムには、position: static;のままでもz-indexが効きます。

次の例では、.cardがGridアイテムです。カード同士が同じマスで重なるため、z-index: 2;のカードAがカードBの前に出ます。

<div class="cards">
  <div class="card card--a">カードA</div>
  <div class="card card--b">カードB</div>
</div>
.cards {
  display: grid;
}
.cards > .card {
  grid-area: 1 / 1;
  padding: 24px;
  background: #f5f6f2;
  border: 2px solid #536048;
}
.cards > .card--a {
  z-index: 2;
}
.cards > .card--b {
  z-index: 1;
  margin: 24px 0 0 24px;
}

これはこの節だけの独立した例です。以下のコードと混ぜずに確認してください。CSSは対応するHTMLを置いたページのスタイルシートへ記述します。

カードのさらに内側にあるラベルまで、自動的にGridアイテムになるわけではありません。「どの親がFlex/Gridで、その直接の子はどれか」を確かめます。並べ方の基本はFlexboxの使い方とGridの使い方で補足しています。

子を9999にしても変わらないときは、親の重なりを見る

親の中の大きな値は、外のグループを追い越せない

重なりの順序をひとまとまりで扱うグループを、重ね合わせコンテキスト(スタッキングコンテキスト)と呼びます。子のz-indexは、その子が属するグループの中で比較されます。

たとえば、カードAの親側の順序が1、カードBが2なら、カードAの中にあるNEWラベルを9999にしても、カードBより手前には出られません。下の図では、カード同士が同じ外側のグループに属しているものとします。

同じ外側のグループでは、z-indexが1のカードA内のNEWラベルを9999にしても、z-indexが2のカードBより前に出られない
同じ外側のグループでは、子の値より先に親同士の順序を比較します。

見るべき比較は、ラベルの9999とカードBの2ではなく、カードAの1とカードBの2です。さらに外側にもグループがある場合は、両方の親をたどり、同じグループ内で比較できる階層まで戻ります。

カード同士が重なる例で、直す場所を確認する

次のHTMLとCSSを、ほかの例とは別に組み合わせて使います。カードAからはみ出したNEWラベルの右側を、カードBが覆う例です。

<div class="stage">
  <div class="card card--a">
    カードA
    <span class="card__badge">NEW</span>
  </div>
  <div class="card card--b">カードB</div>
</div>
.stage {
  display: flex;
  align-items: flex-start;
  padding: 32px;
}
.stage > .card {
  position: relative;
  box-sizing: border-box;
  flex: 0 0 160px;
  min-height: 110px;
  padding: 16px;
  background: #f5f6f2;
  border: 2px solid #536048;
}
.stage > .card--a {
  z-index: 1;
}
.stage > .card--b {
  z-index: 2;
  margin: 28px 0 0 -24px;
}
.stage .card__badge {
  position: absolute;
  top: 36px;
  right: -24px;
  z-index: 9999;
  padding: 6px 12px;
  background: #c28a3d;
  color: #fff;
}

.cardのposition: relative;はラベルの配置基準です。right: -24px;ではみ出させ、カードBの左側に付けた負の余白で、カード同士を重ねています。この例には切り取りの指定はありません。

カードA全体を前に出したいなら、上の.stage > .card--aの値を次のように変えます。

.stage > .card--a {
  z-index: 3;
}

これでカードAのグループがカードBより前になります。3は今回の2より大きい値として選んだだけで、すべてのサイトに共通する推奨値ではありません。

HOAI Point

親の順序を上げると、その中の画像やボタンもまとめて前に出ます。ラベルだけを前に出したい場合は、カード全体を上げる修正が目的に合うか確認しましょう。合わない場合は、ラベルを重なりのグループの外へ移すなど、HTMLの構造から検討します。

transformやopacityでもグループができる

すべての親要素が、独立した重なりのグループを作るわけではありません。代表的な条件は次のとおりです。

親にある指定グループを作る条件
positionとz-indexrelativeまたはabsoluteで、z-indexがauto以外
position: fixed/stickyz-index: auto;でも作る
Flex/Gridアイテムのz-indexauto以外の値を指定する
transformnone以外。移動量が0でも作る
opacity1より小さい値。0.99でも作る
isolationisolateを指定する

アニメーション用のtransform: translateY(0);や、透明度のopacity: 0.99;が原因になることもあります。ほかにもfilterやcontainなどに条件があるため、該当しない場合はMDNの重ね合わせコンテキストの作成条件を確認します。

原因かどうかを調べるときは、一時的にその指定を無効にして表示を比べます。ただし、transformは位置や大きさにも関わります。無効化して直ったからといって、そのまま削除せず、必要な見た目を保てる修正を選んでください。

親の端で切れるときはoverflowを確認する

overflowは、要素の領域からはみ出した内容をどう扱うかを決める指定です。hiddenやclipでは外側を切り取り、autoやscrollでも表示領域の外側はそのまま見せません。

この切り取りは重なり順とは別に働きます。NEWラベルが親の境界で欠けているなら、子を前に出す前に「どの親が外側を切っているか」を確認します。

カード全体にoverflow:hiddenがあるとNEWラベルも欠けるが、画像領域だけを切り取ればラベルを外に出せる
切り取る範囲を画像側へ分けると、兄弟要素のラベルを外へ表示できます。

角丸のカード全体にoverflow: hidden;を付けると、はみ出したラベルも切れることがあります。画像だけを角丸に収めたいなら、切り取る役割を内側の画像用要素へ移す方法が使えます。

次は、カードから出るラベルと、切り取る画像領域を分けた独立例です。色の付いた領域を画像に見立てています。

<div class="clip-card">
  <div class="clip-card__media">画像の領域</div>
  <span class="clip-card__badge">NEW</span>
</div>
.clip-card {
  position: relative;
  width: 240px;
  margin: 32px;
  overflow: visible;
}
.clip-card__media {
  min-height: 140px;
  padding: 16px;
  border-radius: 16px;
  overflow: hidden;
  background: #f5f6f2;
}
.clip-card__badge {
  position: absolute;
  top: -12px;
  right: -12px;
  z-index: 1;
  padding: 6px 12px;
  background: #c28a3d;
  color: #fff;
}

ラベルは画像用要素の子ではなく、兄弟として置いています。これにより、画像側のoverflow: hidden;の切り取り対象から外れます。さらに外側の親が切り取っている場合は、その親も確認が必要です。

スクロール領域のoverflow: auto;を安易にvisibleへ変えると、スクロールやレイアウトが崩れることがあります。切り取りが必要な親なら、ラベルやメニューをその外へ置く構造を検討します。clip-pathやマスクによる切り取りも、z-indexだけでは解除できません。

また、overflow-x: hidden;とoverflow-y: visible;を組み合わせても、縦方向が必ずはみ出せるとは限りません。この組み合わせでは縦方向の算出値はautoになります。両方向の実際の値を確認してください。詳しい組み合わせはMDNのoverflowの説明を参照できます。

修正は一つずつ試し、保存後の表示で確かめる

原因を調べる段階では、複数の指定を一度に変えず、変更前と変更後を比べます。検証用のHTML・CSSを用意し、元に戻せるようにしてから試してください。

ブラウザーの開発者ツールを使うと、ページに適用されているCSSを一時的に変えて比較することもできます。Chromeでの操作方法は、Chrome公式のCSSの表示と変更の説明を参照してください。以下は、使うエディターにかかわらず共通する修正の確認順です。

STEP
元の値を控え、修正候補を一つだけ試す

症状に合う節で確認した指定だけを変えます。親の重なりの例ならカードAの1を3へ、切り取りの例なら画像とラベルの置き場所を分けます。NEWラベルが見えるかを比べ、変わらなければいったん元に戻して別の親を調べます。

STEP
必要な変更をCSSへ保存する

表示が直る条件を確認できたら、実際に読み込んでいるスタイルシートへ必要な修正を保存します。構造を変えた場合はHTMLも保存します。開発者ツール上だけの変更は、通常は再読み込みで失われます。

STEP
再読み込みして、スクロールと操作も確認する

ページを再読み込みし、修正が残っていることを確認します。画面の幅を狭くしたときやスクロールしたときも、ラベル・メニューが欠けず、ほかのボタンやリンクを覆っていないかを見ます。意図した要素が見え、必要な場所をクリックできれば完了です。

まとめ:数値を増やす前に、変更する階層を決める

z-indexを変えても前に出ないときは、対象に値が効くか、親のグループに制限されていないか、親の外側で切られていないかを確認します。

子だけの順序なら子を、カード全体の順序なら比較する親を修正します。切り取りが原因なら、overflowの役割とHTMLの構造を見直しましょう。原因に合う修正で表示が直り、スクロールや操作にも問題がなければ、そこで確認を終えて大丈夫です。

この記事を書いた人

横畑デザイン事務所代表。Webデザイナー・プログラミング講師として、WordPressを中心としたWebサイトの制作・運用と個別指導に携わっています。実際の制作や指導で培った知識と経験をもとに、Web制作やAI活用について、初心者が迷わず一歩を踏み出せる情報を分かりやすく発信しています。

目次