opacityとスタッキングコンテキストに立ち向かう
- 掲載日
スタッキングコンテキスト(重ね合わせコンテキスト)とは
重ね合わせコンテキスト (Stacking context) は、ビューポートまたはウェブページに面していると想定されるユーザーに対する仮想的な Z 軸に沿って並べられた HTML 要素の三次元の概念化です。
cssでは、z-indexやfloat、position等を使う時に、要素同士のどっちを前面に表示するか決めるために内部的にはz軸を持っているというお話です。
このz軸は、特定のスタイルを持っていない場合は概念が存在しない(要素は一番下に張り付く)のですが、opacity等を設定するとこの概念が適用されて要素が浮かび上がります。
以下のようなHTMLを作ってブラウザで開き、「要素1」と「要素2」が重なる位置にカーソルを合わせると、添付gifのようなチラつきが起こります。(点滅注意)

<!DOCTYPE html>
<html>
<head>
<style>
.element:hover {
opacity: 0.6;
}
.element>div {
position: fixed;
color: white;
width: 100px;
height: 100px;
}
.element1>div {
top: 50px;
left: 0;
background-color: rgb(255, 75, 0, 1);
z-index: 2;
}
.element2>div {
top: 100px;
left: 50px;
text-align: end;
background-color: rgb(0, 90, 255, 1);
z-index: 99;
}
</style>
</head>
<body>
<p>
要素1と要素2が重なる位置にカーソルを当てるとスタッキングコンテクストによってちらつきが起きる
</p>
<div class="element element1">
<div>
要素1(z-index:2)
</div>
</div>
<div class="element element2">
<div>
要素2(z-index:99)
</div>
</div>
</body>
</html>その原因がこのスタッキングコンテキストまわりの仕様にあり、以下のような動作をします。
- hover時に要素2に
opacityが設定されるため、親要素が浮かび上がる。 - 要素2の親要素は
z-index:2の要素1に負けて後ろに回る。 - 要素2のhoverが解除され、要素2のopacityスタイルが削除される。
- 再び要素2の方が上だと判定され、hoverされる。
- 1に戻り、hoverイベントが評価されなくなるまでループ。(チラつく。)
解決まで苦しめられたのでその備忘録です。
対策
案1. 親要素にposition: static以外 とz-indexを設定する
(※ サンプルのz-indexの値はテストなので適当にデカい数字を入れてますが、実際にやるときはちゃんと計算して設定しましょう。)
それまで浮かんでいなかった親要素が浮き上がるのが問題なので、最初から浮かせておこうという解決策。
浮き上がる親要素に最強のz-indexを設定すれば必ず一番上に来るので固定できます。
.element:hover {
opacity: 0.6;
position: relative; /* ここを追加 */
z-index: 99999; /* ここを追加 */
}position指定入れてしまうこと自体がNG(表示位置が変わってしまう等)なケースもあるので注意。
案2. opacityの位置を合わせる
親要素を浮かせない解決をしたい時はこっちになるのかなぁと。
元からz-indexの存在する子要素でhover時にopacityを付けるようにしてもOKです。
.element>div:hover { /* ここを修正 */
opacity: 0.6;
}ただ、これもケースバイケースで、親要素の中に他の要素があるとその部分は透過しなくなるのでNGだったりすると思います。
もっといい解決策はありそうですが、自分はとりあえずこの二つでなんとかしました。
(おまけ)Edgeで3Dで要素の重なりが見れる
Edge ブラウザでは開発者ツールで3Dで要素の重なりを見ることができます。

添付のように、要素1が要素2の上に浮き上がってきていることが視覚的に分かりやすくみられます。
記事ではシンプルな構成にしているのでこんなリッチな機能を使わずとも構いませんが、実際の画面はもっと複雑な子孫要素があり、重なった状態になっていると思うので、今回のようなスタイルのちらつきや、それ以外でもスタッキングコンテキストが複雑に絡んでいるレイアウトで悩んでるときの調査に役に立ちそうです。
参考リンク
- 君は真に理解しているか?z-indexとスタッキングコンテキストの関係
正直MDNのページは難しく、こちらの図解ありサイト様のおかげでなんとか理解出来ました。 - MDNの重ね合わせコンテキストのページ
内容は難しくて正直サッパリなんですが、なるべく正確な用語を使うために確認用として利用。

この記事を書いた人
- A.W.
- 茨城県在住Webエンジニアです。 PHP、PostgreSQL、Linuxなどを業務で使用しています。 趣味ではGoやNuxt、Flutterをやってます。