2024年04月16日
近ごろのCSSは、想像を超えるほど高機能になってきていて、「CSSだけで、ここまでできるの?!」と驚くばかりです。その一方で、使いこなすためには抽象的な概念を理解せねばならず、「せっかくの機能なのに、なぜか効果が現れない」といった悩みも多くなっていることでしょう。
こんかいは、CSSの「フィルタ」を例に、その「抽象的な概念」について、さらっと触れてみようと思います。
よくある例
すりガラスのような、背景がぼやけて見える、CSSの「フィルタ」を利用して、カードが並んだようなページを作ろうとしました。こんなタイプのものです。
See the Pen 重ね合わせコンテキストとフィルタ1 by isobeact (@rmzpacpm-the-builder) on CodePen.
しかし、なぜかうまく行かなかった経験はありませんか? 例えば、このような感じに。
See the Pen 重ね合わせコンテキストとフィルタ2 by isobeact (@rmzpacpm-the-builder) on CodePen.
ピンクのストライプは、カード単位で、ぼんやりぼやけて見えるようにフィルタ設定しているはずなのですが、なぜか無視されています。それに、カード自体にも白い色をつけていたはずなのに、それが反映されていませんね。
では、なぜ下の例ではフィルタがかからないのでしょうか? ヒントは先ほどお話しした「抽象的な概念」です。
「重ね合わせコンテキスト」
それは「重ね合わせコンテキスト」と呼ばれる概念です。そもそも「コンテキスト」という言葉自体、なじみのない方も多いと思います。コンテキストとは何かをくわしく解説すると記事が長くなるので、ここでは「前に置くことで、後ろの表現の意味を変えてしまうもの」くらいに思っていただければOKです。
それでは、さきほどのコードを、HTMLとCSSに分けて、眺めてみましょう。
<main>
<section class="card-container">
<article class="card">
<h1>カードのタイトル</h1>
<!-- 以下略 -->
main {
background-image: (ストライプ模様);
}
.card-container {
filter: drop-shadow(
4px 4px 4px rgba(0, 0, 0, 0.5)
);
}
.card {
backdrop-filter: blur(3px);
}
この記述から生み出される「重ね合わせコンテキスト」とは、どういうものになるのでしょうか?
コンテキストが生まれる条件
さきほどご紹介したリンクの説明から、一部抜粋します。
- 文書のルート要素 (
<html>
) - 以下のプロパティの何れかが
none
以外の値を持つ要素。transform
filter
perspective
clip-path
mask
/mask-image
/mask-border
<body>(<html>)
は暗黙的なコンテキストで、ルートコンテキストとも呼ばれます。上記のような操作をしない限り、マークアップはコンテキストを作らず、平坦になります。つまりあらゆる要素は、同じコンテキスト内の「きょうだい」です。
しかし、さきの例は違います。
card-container
, card
要素で、それぞれフィルタを使っています。そのため、上図のように main
, card-container
, card
は、それぞれが入れ子の、別コンテキストになるのです。
フィルタがかかるのは、直接の親コンテキストのみ!
背景ぼかしフィルタが定義されているのは、card
要素です。そしてフィルタは、直接の親コンテキストのみにしかかかりません!
では、これを証明するために、 card-container
のドロップシャドウのフィルタを card
に移すことで、コンテキスト分岐を移動してみましょう。
See the Pen 重ね合わせコンテキストとフィルタ1 by isobeact (@rmzpacpm-the-builder) on CodePen.
うまくフィルタがかかりましたね! 図にすると、こうなった状態です。
このように、重ね合わせコンテキストは「ついうっかり」できてしまいがちなので、CSSは、実は細心の注意を払って設計しなければならないのです…。
「俺たちは雰囲気でz-indexを使っている」から卒業しよう
重ね合わせコンテキストが「うっかり」できないようにするには、「どのようなタイミングで生まれるのか」を、いつでも調べられるようにしておくことです。z-index:10001;
などといった雰囲気コンテキストは、よほどのことだと常に心がけておきましょう。
こんかいの記事は、以上です。それでは、よきコーディングライフを!