: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() — ゼロ詳細度(簡単にオーバーライド可能)