メインコンテンツまでスキップ
  • Created:
  • Updated:
  • Author:
    Takeshi Takatsudo

:is()と:where()セレクター

問題

同じ宣言を共有するCSSセレクターは、すべての組み合わせを個別に書く必要があり、冗長で繰り返しの多いルールセットになります。異なる詳細度レベルのセレクターリストは、簡単にオーバーライドできるベーススタイルの作成を困難にします。リセット、デフォルト、ライブラリCSSを構築する際、コンシューマーのスタイルとの詳細度の競合は常に課題です。AIエージェントは通常、繰り返しの多いセレクターを生成し、詳細度を意図的に管理するために:is():where()を使うことはほとんどありません。

解決方法

:is():where()は、セレクターリストを受け取り、そのリストの少なくとも1つのセレクターに一致する要素をマッチさせる関数擬似クラスセレクターです。セレクターをグループ化することで繰り返しを減らします。重要な違いは詳細度です:

  • :is() は最も具体的な引数の詳細度を取る
  • :where() は常にゼロの詳細度(0, 0, 0)を持つ

これにより、:where()は簡単にオーバーライドできるべきデフォルト/ベーススタイルに最適であり、:is()は詳細度を保持しながらセレクターをグループ化するのに適しています。

コード例

:is()によるセレクターの繰り返し削減

/* Without :is() — verbose and repetitive */
article h1,
article h2,
article h3,
section h1,
section h2,
section h3,
aside h1,
aside h2,
aside h3 {
line-height: 1.2;
}

/* With :is() — concise */
:is(article, section, aside) :is(h1, h2, h3) {
line-height: 1.2;
}

:where()によるゼロ詳細度のデフォルト

どんな単一クラスでも簡単にオーバーライドできるベーススタイルを作成します。

/* Base styles with zero specificity — trivially overridable */
:where(h1, h2, h3, h4, h5, h6) {
margin-block: 0;
font-weight: 700;
}

:where(ul, ol) {
padding-left: 1.5rem;
}

:where(a) {
color: #2563eb;
text-decoration: underline;
}

/* Any class override wins without specificity battles */
.nav-link {
color: inherit;
text-decoration: none;
}

オーバーライド可能なリセットの構築

/* A reset that never fights with author styles */
:where(*, *::before, *::after) {
box-sizing: border-box;
margin: 0;
padding: 0;
}

:where(html) {
line-height: 1.5;
-webkit-text-size-adjust: 100%;
}

:where(img, picture, video, canvas, svg) {
display: block;
max-width: 100%;
}

:where(input, button, textarea, select) {
font: inherit;
}

:is():where()の戦略的な組み合わせ

詳細度を寄与させたい部分には:is()を、ゼロにしたい部分には:where()を使用します。

/* The .article class contributes specificity (0,1,0),
but the element selectors inside :where() add nothing */
.article :where(p, li, blockquote) {
line-height: 1.8;
max-width: 65ch;
}

/* Override with just a class — no specificity fight */
.compact-text {
line-height: 1.4;
}

寛容なセレクターリスト

:is():where()の両方が寛容なセレクターリストを使用します。リスト内の無効なセレクターがルール全体を無効にすることはありません。

/* If :未来的-selector is invalid, the rest still works */
:is(.card, .panel, :未来的-selector) {
border-radius: 8px;
}

/* Without :is(), one invalid selector breaks the entire rule */
/* .card, .panel, :未来的-selector { border-radius: 8px; } — entire rule is dropped */

ネストされたセレクターの簡略化

/* Complex nesting without :is() */
.sidebar nav ul li a,
.sidebar nav ol li a {
color: #374151;
text-decoration: none;
}

/* Simplified with :is() */
.sidebar nav :is(ul, ol) li a {
color: #374151;
text-decoration: none;
}

詳細度の比較

/* :is() specificity = highest argument */
:is(.class, #id) p {
/* Specificity: (1, 0, 1) because #id is the highest */
color: blue;
}

/* :where() specificity = always zero */
:where(.class, #id) p {
/* Specificity: (0, 0, 1) — only the p contributes */
color: blue;
}

/* A simple class wins over :where(#id) */
.text {
/* Specificity: (0, 1, 0) — wins over :where(#id) p's (0, 0, 1) */
color: red;
}

ライブラリ/デザインシステムパターン

/* Design system default — zero specificity via :where() */
:where(.ds-button) {
padding: 0.5rem 1rem;
border: 1px solid #d1d5db;
border-radius: 4px;
background: white;
cursor: pointer;
}

:where(.ds-button.primary) {
background: #2563eb;
color: white;
border-color: #2563eb;
}

/* Consumer can override with just a class — no !important needed */
.my-button {
background: #16a34a;
border-color: #16a34a;
}

ブラウザサポート

  • Chrome 88+
  • Firefox 78+
  • Safari 14+
  • Edge 88+

:is():where()の両方がグローバルサポート96%を超えています。プロダクション利用に安全です。

AIがよくやるミス

  • :where()の存在を知らず、詳細度の競合を引き起こす冗長なセレクターリストを生成する
  • :where()の方が適切な場合に:is()を使用する(例:簡単にオーバーライドできるべきベース/リセットスタイル)
  • セレクターの全組み合わせを手動で書き出し、:is()でグループ化しない
  • ライブラリ/デザインシステムCSSでコンシューマーとの詳細度競合を避けるために:where()を活用しない
  • 詳細度の動作を混同する — :is():where()のようにゼロ詳細度だと思い込む
  • :is():where()が寛容なセレクターリストを使用すること(無効なセレクターがルールを壊さない)を認識していない
  • :where()なら簡単にオーバーライドできたはずのベーススタイルのオーバーライドに!importantを使用する

使い分け

  • :is():詳細度を保持しながら繰り返しを減らすためにセレクターをグループ化する
  • :where():ゼロ詳細度のベーススタイル、リセット、デザインシステムのデフォルトを作成する
  • 両方:未知または将来のセレクターを適切に処理する寛容なセレクターリストを構築する
  • ライブラリCSSには:where():コンシューマーのスタイルが常に!importantなしでオーバーライドできることを保証する
  • 組み合わせ:セレクターの詳細度を寄与させる部分に:is()を、ゼロ詳細度の部分に:where()を使用する

ライブプレビュー

:is() — セレクターのグループ化
:where() — ゼロ詳細度(簡単にオーバーライド可能)

参考リンク