CSS 疑似クラス :is() と :where()

CSS の関数疑似クラス :is():where() の使い方についての覚書です。

作成日:2024年4月2日

:is()

:is() は、引数に渡されたセレクターのいずれかと一致する全ての要素を選択する関数疑似クラスです。

:is() を使用すると、セレクターの繰り返しを減らすことができます。

例えば、以下の記述は

.foo button:hover,
.bar button:hover,
.baz button:hover {
  color: red;
} 

:is() を使って以下のように記述することができます。

この場合、引数に3つのセレクター(.foo, .bar, .baz)を渡して、それらのいずれかの子要素の button:hover の文字色を設定しているので、上記と同じことになります。

:is(.foo, .bar, .baz) button:hover {
  color: red;
}

同様に以下は、

section.foo h2,
section.bar h2,
section.baz h2 {
  color: tomato;
}

:is() を使って以下のように記述することができます。

section:is(.foo, .bar, .baz) h2 {
  color: tomato;
}

:is() を組み合わせて使用することもできるので、例えば、以下は

:is(section, article):is(.foo, .bar) h2 {
  color: tomato;
}

以下と同じことです。

section.foo h2,
section.bar h2,
article.foo h2,
article.bar h2 {
  color: tomato;
} 

以下は :is() を使って異なる深さの h2 要素にスタイルを適用する例です。

:is() を使わない場合、とても複雑になります(参考元:MDN :is() section セレクターの簡略化)。

/* レベル 1 */
:is(section, article, aside, nav) h2 {
  font-size: 25px;
}
/* レベル 2 */
:is(section, article, aside, nav) :is(section, article, aside, nav) h2 {
  font-size: 20px;
}
/* レベル 3 */
:is(section, article, aside, nav)
  :is(section, article, aside, nav)
  :is(section, article, aside, nav)
  h2 {
  font-size: 15px;
}

詳細度

:is() の詳細度は、引数で与えられたセレクターの中で最も詳細度が高いものになります。

例えば、以下のような HTML があり、

<p>text</p>
<p class="foo">text</p>
<p id="bar">text</p>

以下の CSS を記述すると、

p {
  color: cornflowerblue;
}

.foo {
  color: forestgreen;
}

#bar {
  color: tomato;
}

以下のように表示されます。

text

text

text

CSS を以下のように書き換えると、

/* :is(p, #qux) を上記の先頭に追加 */
:is(p, #qux) {
  color: plum;
}

p {
  color: cornflowerblue;
}

.foo {
  color: forestgreen;
}

#bar {
  color: tomato;
}

:is(p, #qux) は引数のセレクターに ID セレクター #qux を持っているので、詳細度が p.foo より高くなるため、p.foo の文字色は plum になります(#qux が存在するかどうかは関係なし)。

#bar は詳細度の高い ID セレクターなのと、:is() の後に記述されているため、文字色は指定した tomato になります。もし、:is(p, #qux) の記述が #bar の記述の後であれば、文字色は plum になります。

text

text

text

寛容なセレクター解析

CSS はセレクターリストを使用している(複数のセレクターをカンマ区切りで指定している)場合、その中のセレクターのいずれか1つでも無効な場合、リスト全体が無効とみなされます。

例えば、以下の場合、:abc という疑似セレクターは存在しないので、セレクター.bar:abc は無効と解析されて、リスト全体が無効とみなされます。そのため、.foo に color: red は適用されません。

.foo, .bar:abc {
  color: red;
 }

:is() と次項の :where() は特別で、無効なセレクターが存在してもリスト全体が無効とみなされるのではなく、無効なセレクターは無視され、他のセレクターが使用されます。

以下のように :is() または :where() を使うと、無効なセレクターは無視され、有効なセレクターは機能するので、 .foo にはスタイルが適用されます。

:is(.foo, .bar:abc) {
  color: red;
 }

/* または */
:where(.foo, .bar:abc)  {
  color: red;
 }

一部のブラウザでしかサポートされていないセレクタを使用する場合などに利用できそうです。

Forgiving Selector List(Selectors Level 4)

サポート状況

:is() は2021年1月からすべてのモダンブラウザで利用できるようになっています。現在では多くのデバイスやブラウザのバージョンで動作します。

詳細は以下で確認することができます。

https://caniuse.com/css-matches-pseudo

参考情報

:is() の詳細は以下で確認できます。

:where()

:where() は :is() と同様、引数に渡されたセレクターのいずれかと一致する全ての要素を選択する関数疑似クラスです。

:where() と :is() の違いは、:is() は引数内で最も詳細度の高いセレクターの詳細度になるのに対して、:where() はセレクター全体の詳細度を高めない(詳細度が常に 0 である)ということだけです。

例えば、以下のような HTML がある場合、

<div class="foo">
  text (.foo)
</div>

<p>text (p)</p>

<div class="bar">
  text (.bar)
</div>

:where() を使って、以下を記述すると、p と .foo 及び .bar にマッチする全ての文字色が cornflowerblue になります。

:where(p, .foo, .bar) {
  color: cornflowerblue;
}
text (.foo)

text (p)

text (.bar)

CSS を以下のように書き換えると、

:where(p, .foo, .bar) {
  color: cornflowerblue;
}

/* 以下を追加 */
p, div {
  color: tomato;
}

.foo {
  color: forestgreen;
}

:where() はセレクター全体の詳細度を高めない(詳細度が常に 0 である)ため、詳細度の低いセレクターを使って設定を上書きすることができます。

text (.foo)

text (p)

text (.bar)

:is() に書き換えると、:is() はセレクターの中の最も高い詳細度になるので、p, div の設定より優先されます。

/* :is() は詳細度を持つ */
:is(p, .foo, .bar) {
  color: cornflowerblue;
}

p, div {
  color: tomato;
}

.foo {
  color: forestgreen;
}
text (.foo)

text (p)

text (.bar)

サポート状況

:where() は :is() と同様、2021年1月からすべてのモダンブラウザで利用できるようになっています。現在では多くのデバイスやブラウザのバージョンで動作します。

詳細は以下で確認することができます。

https://caniuse.com/css-matches-pseudo

参考情報

:where() の詳細は以下で確認できます。