2026年8月4日

2026年8月4日

CSSの:is()と:where()の使い方|詳細度の違いとWordPressでの使い分け

:is() と :where() は、セレクターの一部をカンマ区切りの候補でまとめて書ける疑似クラスです。.entry-content h2 a, .entry-content h3 a, .entry-content h4 a のような繰り返しを .entry-content :is(h2, h3, h4) a の1行にできます。

2つの書き方は同じで、違うのは詳細度(セレクターの強さ)だけです。この違いを知っておくと、WordPressのテーマや追加CSSで「書いたのに効かない」「あとから上書きできない」を減らせます。

基本の書き方

カッコの中に、カンマ区切りでセレクターを並べます。カッコの中のどれか1つに一致すれば、その位置が一致したものとして扱われます。

/* 従来の書き方 */
.entry-content h2 a,
.entry-content h3 a,
.entry-content h4 a {
  text-decoration: underline;
}

/* :is() でまとめた書き方(意味は同じ) */
.entry-content :is(h2, h3, h4) a {
  text-decoration: underline;
}

組み合わせが増えるほど効果が大きくなります。次の例は、従来の書き方なら 2 × 3 = 6 個のセレクターが必要です。

:is(.entry-content, .wp-block-post-content) :is(ul, ol, blockquote) {
  margin-block: 1.5em;
}

:where() も書き方はまったく同じです。

.entry-content :where(h2, h3, h4) a {
  text-decoration: underline;
}

:is() と :where() の違いは詳細度だけ

詳細度は、セレクターに含まれる「ID・クラス(属性・疑似クラスを含む)・要素」の数で決まる強さで、ここでは(ID, クラス, 要素)の3つの数で表します。

  • :is() の詳細度は、カッコ内でいちばん強いセレクターの詳細度になります
  • :where() の詳細度は、中身にかかわらず常に0です
セレクター 詳細度
.entry-content h2 a (0, 1, 2)
.entry-content :is(h2, h3) a (0, 1, 2)
.entry-content :is(h2, .title) a (0, 2, 1)
.entry-content :where(h2, .title) a (0, 1, 1)
:where(.entry-content h2 a) (0, 0, 0)

3行目に注意してください。:is(h2, .title) は、実際に一致したのが h2 でも、カッコ内でいちばん強い .title の詳細度で数えられます。:is() の中にIDを1つでも入れると、ルール全体がID並みに強くなります。

/* #main ではなく .sidebar の中のリンクに一致した場合でも、詳細度は (1, 0, 1) */
:is(#main, .sidebar) a {
  color: #1e1e1e;
}

どちらを使うか

  • あとから上書きされる前提の「初期値」を書くときは :where()。詳細度が0なので、クラス1つのセレクターで上書きできます。テーマやプラグインの配布用CSS、リセットCSSに向いています
  • 従来の書き方をそのまま短くしたいときは :is()。カンマで並べていたときと同じ強さになるので、既存のCSSを書き換えても優先順位が変わりにくくなります

カッコの中は「寛容なセレクターリスト」

通常のカンマ区切りのセレクターは、1つでもブラウザが解釈できないものが混ざると、ルール全体が無効になります。:is() と :where() の中は、解釈できない候補だけを無視して残りを有効にします。

/* 未対応の疑似クラスが混ざると、ルール全体が無効になる */
input:focus-visible,
input:-unknown-pseudo {
  outline: 2px solid #3858e9;
}

/* :is() の中なら、解釈できない候補だけが無視される */
input:is(:focus-visible, :-unknown-pseudo) {
  outline: 2px solid #3858e9;
}

ただし、:is() や :where() そのものに対応していない古いブラウザでは、ルール全体が無視されます。

WordPressで使いどころになる場面

コアのスタイルはすでに :where() で弱めてある

WordPress 6.6 以降、theme.json やグローバルスタイル(サイトエディターの「スタイル」)から出力されるブロックのスタイルは、:root :where(.wp-block-button .wp-block-button__link) のような形で、詳細度が (0, 1, 0) にそろえられています(WordPress公式の開発者ノート「WordPress 6.6 CSS Specificity」による)。

このため、追加CSSでブロックの見た目を変えるときは、クラス1つ程度の強さで足ります。詳細度が同じなら後に書かれたものが勝ち、「外観 > カスタマイズ > 追加CSS」の内容はグローバルスタイルより後に出力されます。!important を足す前に、開発者ツールで相手のセレクターの詳細度を確認してください。

/* グローバルスタイルのボタン色を、追加CSSで上書きする */
.wp-block-button__link {
  border-radius: 999px;
}

自作ブロックやテーマの初期スタイルを :where() で書く

自作のブロックや配布するテーマでは、初期スタイルを :where() で包んでおくと、利用者がクラス1つで上書きできます。WordPress 6.6 の開発者ノートでも、独自ブロックの既定スタイルは :root :where() で包んで詳細度をそろえるよう案内されています。

/* 自作ブロックの既定スタイル(詳細度 (0, 1, 0)) */
:root :where(.wp-block-myplugin-notice) {
  padding: 1em 1.25em;
  border-left: 4px solid #3858e9;
  background: #f0f4ff;
}

/* 利用者側:クラス1つで上書きできる */
.is-style-warning {
  border-left-color: #d63638;
  background: #fcf0f1;
}

本文の見出しや要素をまとめて整える

記事本文のスタイルをまとめて書くときは、:is() で読みやすくできます。クラシックテーマでは .entry-content、ブロックテーマでは .wp-block-post-content が本文を囲むクラスであることが多いので、両方に当てたい場合は次のように書けます(実際のクラス名はテーマごとに開発者ツールで確認してください)。

:is(.entry-content, .wp-block-post-content) :is(h2, h3) {
  scroll-margin-top: 80px;
}

:is(.entry-content, .wp-block-post-content) :is(h2, h3, h4):first-child {
  margin-top: 0;
}

つまずきやすい点

  • 疑似要素は入れられない: ::before や ::after は :is() や :where() の中では一致しません。.card:is(::before) ではなく :is(.card, .panel)::before のように外に書きます
  • :is() にIDを混ぜない: 前述のとおり、候補の1つでもIDならルール全体が強くなり、後から上書きしにくくなります
  • :where() で書いたスタイルが負ける: 詳細度が0なので、テーマ側の要素セレクター1つ(例: a { color: … })にも負けることがあります。意図して弱くしたい場面以外は :is() を使います
  • 入れ子にしたCSSとの関係: CSSネスト(入れ子)で親が複数のセレクターのとき、& は親を :is() で包んだのと同じ扱いになります。親にIDが含まれると詳細度が上がる点は同じです

ブラウザの対応状況

:is() と :where() は、Chrome・Edge 88、Firefox 78、Safari 14 以降で使えます(2026年11月時点)。主要ブラウザで使えるようになってから数年たっており、通常のサイトでは代替手段を用意する必要はほとんどありません。

動作を確認する

ブラウザの開発者ツールで要素を選ぶと、「Styles(スタイル)」パネルに適用中のルールが並び、負けた宣言には取り消し線が付きます。Chrome や Edge では、セレクターにマウスを合わせると詳細度が表示されるので、:is() と :where() を入れ替えたときの変化を確かめられます。CSSを書き換えても表示が変わらない場合は、ブラウザやキャッシュ系プラグインのキャッシュも疑ってください。

まとめ

  • :is() と :where() は、セレクターの一部をカンマ区切りの候補でまとめて書く疑似クラス
  • 違いは詳細度だけで、:is() はカッコ内で最も強い候補、:where() は常に0
  • 上書きされる前提の初期スタイルは :where()、既存の書き方を短くするだけなら :is()
  • WordPress 6.6 以降、グローバルスタイルのブロック用CSSは :root :where() で (0, 1, 0) にそろえられているので、追加CSSはクラス1つ程度で上書きできる
  • 疑似要素はカッコの中に入れられない。:is() にIDを混ぜると全体が強くなる

お気軽にご相談ください

お見積りへ お問い合わせへ
▲