z-index 同士の競合を isolation: isolate; で解消する
この記事で分かること
isolation: isolate;
がどのような場面で有用かを解説します。
複数のコンポーネントを配置したとき、それぞれの z-index
が競合したケースを例に用います。
前提
それぞれ position: absolute;
の要素を内包する、 2 つのコンポーネントを横並びで配置します。
デモ
メニューに hover してみてください。デフォルトでは、表示される子メニューが他のコンポーネントの z-index
に負け、表示が崩れてしまいます。
「z-index の競合を解決する」ボタンを押下すると、子メニューが正しく表示されるようになります。
解説
実装コード
2 つのコンポーネントを、 マウスオーバーメニュー
と カード
と命名します。それぞれは、構成要素で以下の z-index
を保有しています。
.mouseover-menu {
&__child {
z-index: 1;
}
}
.card {
&__bar {
z-index: 1;
}
&__badge {
z-index: 2;
}
}
個別のコンポーネント単位で見れば、これらの z-index
の付与は適切であると言えます。しかし、同じ画面に配置したとき、互いの z-index
が競合して表示崩れが起きてしまいました。
では、「z-index の競合を解決する」ボタンはどのような魔法を使ったのでしょうか?
.card {
&[data-is-isolate="true"] {
isolation: isolate;
}
}
CodePen 上で行っているのは、 カード
のデータ属性の値を変更し、 isolation: isolate;
が適用されるようにしただけです。
マウスオーバーメニュー
の z-index
を 1000000000
にするなど、レベルを上げて物理で殴ったわけではありません。
isolation: isolate; をざっくり説明する
MDN の該当ページはこちらです。
新しい重ね合わせコンテキストが必ず作成されます。
上記 MDN のリンクを辿ればより詳しく、正しい仕様が説明されているので、この記事では isolation: isolate;
をざっくりレベルで解説します。
デフォルトでは、 マウスオーバーメニュー
と カード
の z-index
はこのような状態にあります。
親要素のレイヤー(コンテキスト)に、同じ z-index
が配置されています。 競合した結果、 カード
の重なりの方が勝ってしまいました。
それでは、 isolation: isolate;
で カード
を囲ってみましょう。
カード
に新しいコンテキストが作成されたことにより、 カード
が内包する要素の z-index
はそのコンテキスト内で留まるようになりました。他のコンテキストに影響することはありません。
これで、親要素直下に置かれた重ね合わせの指定は マウスオーバーメニュー
の z-index: 1;
のみになります。同じコンテキストで競合する重なりがなくなったため、 マウスオーバーメニュー
が意図通りに表示されました!
isolation: isolate; を用いる際の注意点
z-index
を用いるコンポーネント全てに isolation: isolate;
を付与すればよいのかというと、そうではありません。
マウスオーバーメニュー
の例を挙げると、この UI は「マウスオーバーのメニューは、他のコンポーネントよりも上位に表示する」という仕様があります。他のコンテキストより上に表示される必要があるため、保持する z-index
が自身のコンテキストに留まってはならないのです。
試しに マウスオーバーメニュー
にも カード
と同様の指定をすると、見切れが発生してしまいます。
コンポーネントが持つ役割に応じて、他のコンポーネントとの z-index
の関係性を考慮し、適切に isolation: isolate;
を指定する必要があります。
z-index
設計については、スタイル分科会メンバーである hiro さんの記事も併せてご覧いただければと思います。
まとめ
この記事を読んでくださった何名かは、「せっかくだから俺はこの 1000000 の数字を選ぶぜ!」「じゃあ俺は桁を 1 つ増やして 10000000 にするぜ!」「誰にも負けたくねぇから 9999999999999 にしとくわ」という不毛な z-index
戦争を体験したことがあるのではないでしょうか。そしてこれらの戦いが綺麗に終結した姿を、私は見たことはありません。
しかし、適切な z-index
設計や isolation: isolate;
を用いることができれば、争いは未然に防ぐことができるのです。
プロダクトの治安維持のため、ぜひお試しいただければと思います。
Discussion