【CSS】z-index が効かない原因と解決方法

【CSS】z-index が効かない原因と解決方法 HTML/CSS

要素を重ね順で前面・背面に配置したいときによく使う z-index。しかし、指定しても意図通りに反映されないことがあります。これは CSS の「スタッキングコンテキスト」の仕組みに起因するケースが多いです。この記事では、z-index が効かない原因を整理し、正しい解決方法を紹介します。

z-index の基本

z-index は要素の「スタッキングコンテキスト」内での重なり順を決めるプロパティです。数値が大きいほど前面に表示されます。ただし、z-index が効くのは positionrelativeabsolutefixedsticky の要素だけです。

.front {
  position: relative;
  z-index: 10;
}
.back {
  position: relative;
  z-index: 1;
}

原因1:position が指定されていない

デフォルトの static のままでは z-index が効きません。必ず position を指定しましょう。

.box {
  position: relative; /* static のままでは無効 */
  z-index: 5;
}

原因2:親要素のスタッキングコンテキストに閉じ込められている

親要素が新しいスタッキングコンテキストを作ると、その外側の要素より前面に出すことができません。z-index の数値が大きくても、異なるコンテキスト間では比較されないため「効かない」ように見えます。

.parent {
  position: relative;
  z-index: 1; /* ← 親がコンテキストを作る */
}
.child {
  position: absolute;
  z-index: 9999; /* 親の外には出られない */
}

この場合、親要素の z-index を調整するか、不要な z-index を外してコンテキストを作らないようにしましょう。

原因3:transform や opacity が指定されている

transformopacity < 1filterperspective などを指定すると、新しいスタッキングコンテキストが生成されます。これも子要素の z-index が効かなくなる典型例です。

.parent {
  transform: translateZ(0); /* GPU アクセラレーション目的の指定でもコンテキスト発生 */
}
.child {
  position: absolute;
  z-index: 9999; /* それでも親の外には出られない */
}

解決には transform を外すか、外せない場合は親要素自身の z-index を適切に調整します。

原因4:Flexbox や Grid の仕様

Flexbox や Grid の子要素は、z-index を指定しなくても描画順によって重なりが決まります。さらに z-index を効かせるには position を明示する必要があります。

.flex-item {
  position: relative; /* これがないと z-index が効かない */
  z-index: 10;
}

原因5:負の z-index の扱い

z-index: -1 のように負の値を指定すると、親要素の背景より後ろに描画されます。そのため要素が「消えた」ように見えることがあります。意図的に背面へ送るなら問題ありませんが、表示されないときはこの仕様を確認してください。

よくある解決方法まとめ

  • 必ず position を relative 以上に指定する
  • 親要素が不要に z-index を持っていないか確認する
  • transform や opacity が新しいコンテキストを作っていないか確認する
  • Flex/Grid の子要素は position を付ける
  • 負の z-index は表示順序に注意する

まとめ

z-index が効かないときは「スタッキングコンテキスト」の仕組みを理解すると原因が分かります。単純に数値を大きくするのではなく、親子関係や position、transform の有無を見直すことが正しい解決方法です。