:is() (:matches(), :any())

Этот перевод не завершён. Пожалуйста, помогите перевести эту статью с английского

Это экспериментальная технология
Так как спецификация этой технологии ещё не стабилизировалась, смотрите таблицу совместимости по поводу использования в различных браузерах. Также заметьте, что синтаксис и поведение экспериментальной технологии может измениться в будущих версиях браузеров, вслед за изменениями спецификации.

Примечание: :matches() был переименован в :is() в CSSWG issue #3258.

:is() это функция псевдо-класс CSS принимающая список селекторов как аргумент, и выбирает любой элемент, который может быть выбран одним из селекторов в этом списке. Это полезно при переписи огромных селекторов в более компактную форму.

Заметьте, что в данный момент бразуеры поддерживают ее функционал как :matches(), или даже как более старый, префиксный псевдо-класс — :any(), включая старые версии Chrome, Firefox, и Safari. :any() работает точно таким же образом как и :matches()/:is(), за исключением того, что  :any() требует постановку префиксов и не поддерживает комплексные селекторы.

/* Выбирает какой-либо абзац в шапке, основной части или подвале, который зависал */
:is(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}

/* Пример приведенный выше эквивалентен следующему */
header p:hover,
main p:hover,
footer p:hover {
  color: red;
  cursor: pointer;
}

/* Обратно-совместимая версия с:-*-any() и :matches()
   (Это невозможно сгруппировать селекторы в одно правило,
    так как присутствие одного неверного селектора аннулирует все правило.) */
:-webkit-any(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}
:-moz-any(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}
:matches(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}

Синтаксис

:is( <complex-selector-list> )

где
<complex-selector-list> = <complex-selector>#

где
<complex-selector> = <compound-selector> [ <combinator>? <compound-selector> ]*

где
<compound-selector> = [ <type-selector>? <subclass-selector>* [ <pseudo-element-selector> <pseudo-class-selector>* ]* ]!
<combinator> = '>' | '+' | '~' | [ '||' ]

где
<type-selector> = <wq-name> | <ns-prefix>? '*'
<subclass-selector> = <id-selector> | <class-selector> | <attribute-selector> | <pseudo-class-selector>
<pseudo-element-selector> = ':' <pseudo-class-selector>
<pseudo-class-selector> = ':' <ident-token> | ':' <function-token> <any-value> ')'

где
<wq-name> = <ns-prefix>? <ident-token>
<ns-prefix> = [ <ident-token> | '*' ]? |
<id-selector> = <hash-token>
<class-selector> = '.' <ident-token>
<attribute-selector> = '[' <wq-name> ']' | '[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'

где
<attr-matcher> = [ '~' | | | '^' | '$' | '*' ]? '='
<attr-modifier> = i | s

Примеры

Кроссбраузерный пример

<header>
  <p>Это мой параграф в шапке</p>
</header>

<main>
  <ul>
    <li><p>Это первый</p><p>пункт списка</p></li>
    <li><p>Это второй</p><p>пункт списка</p></li>
  </ul>
</main>

<footer>
  <p>Это мой параграф в подвале</p>
</footer>
:-webkit-any(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}

:-moz-any(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}

:matches(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}

:is(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}
let matchedItems;

try {
  matchedItems = document.querySelectorAll(':is(header, main, footer) p');
} catch(e) {
  try {
    matchedItems = document.querySelectorAll(':matches(header, main, footer) p');
  } catch(e) {
    try {
      matchedItems = document.querySelectorAll(':-webkit-any(header, main, footer) p');
    } catch(e) {
      try {
        matchedItems = document.querySelectorAll(':-moz-any(header, main, footer) p');
      } catch(e) {
        console.log('Your browser doesn\'t support :is(), :matches(), or :any()');
      }
    }
  }
}

matchedItems.forEach(applyHandler);

function applyHandler(elem) {
  elem.addEventListener('click', function(e) {
    alert('This paragraph is inside a ' + e.target.parentNode.nodeName);
  });
}

Упрощение списка селекторов

Псевдо-класс :is() может великолепно упрощать ваши CSS селекторы. К примеру, следующий CSS:

/* 3-уровневые (или более) неупорядоченные списки используют свойство square */
ol ol ul,     ol ul ul,     ol menu ul,     ol dir ul,
ol ol menu,   ol ul menu,   ol menu menu,   ol dir menu,
ol ol dir,    ol ul dir,    ol menu dir,    ol dir dir,
ul ol ul,     ul ul ul,     ul menu ul,     ul dir ul,
ul ol menu,   ul ul menu,   ul menu menu,   ul dir menu,
ul ol dir,    ul ul dir,    ul menu dir,    ul dir dir,
menu ol ul,   menu ul ul,   menu menu ul,   menu dir ul,
menu ol menu, menu ul menu, menu menu menu, menu dir menu,
menu ol dir,  menu ul dir,  menu menu dir,  menu dir dir,
dir ol ul,    dir ul ul,    dir menu ul,    dir dir ul,
dir ol menu,  dir ul menu,  dir menu menu,  dir dir menu,
dir ol dir,   dir ul dir,   dir menu dir,   dir dir dir {
  list-style-type: square;
}

... можно заменить на:

/* 3-уровневые (или более) неупорядоченные списки используют свойство square */
:is(ol, ul, menu, dir) :is(ol, ul, menu, dir) ul,
:is(ol, ul, menu, dir) :is(ol, ul, menu, dir) menu,
:is(ol, ul, menu, dir) :is(ol, ul, menu, dir) dir {
  list-style-type: square;
}

Упрощение селекторов разделов

Псевдо-класс :is()  особенно полезен  при работе с заголовками и разделами HTML5. C тех пор как <section>, <article>, <aside>, и <nav> обычно используют вместе, без :is(), стилизовать их, чтобы они соответствовали друг друг, может быть не просто.

К примеру, без :is(), стилизовать все <h1> элементы на разных уровнях может бы очень сложно:

/* Уровень 0 */
h1 {
  font-size: 30px;
}
/* Уровень 1 */
section h1, article h1, aside h1, nav h1 {
  font-size: 25px;
}
/* Уровень 2 */
section section h1, section article h1, section aside h1, section nav h1,
article section h1, article article h1, article aside h1, article nav h1,
aside section h1, aside article h1, aside aside h1, aside nav h1,
nav section h1, nav article h1, nav aside h1, nav nav h1 {
  font-size: 20px;
}
/* Уровень 3 */
/* ... даже не смей думать об этом! */

Используя :is(), как видно, это гораздо легче:

/* Уровень 0 */
h1 {
  font-size: 30px;
}
/* Уровень 1 */
:is(section, article, aside, nav) h1 {
  font-size: 25px;
}
/* Уровень 2 */
:is(section, article, aside, nav)
:is(section, article, aside, nav) h1 {
  font-size: 20px;
}
/* Уровень 3 */
:is(section, article, aside, nav)
:is(section, article, aside, nav)
:is(section, article, aside, nav) h1 {
  font-size: 15px;
}

Как избежать аннулирования списка селекторов

В отличие от списка селекторов, псевдо-класс :is() не аннулируется, когда из селекторов, попавший туда не поддерживается бразуером.

:is(:valid, :unsupported) {
  ...
}

Будет по прежнему определяться правильно и соответствовать :valid даже в браузерах, которые не поддерживают :unsupported, в то время как:

:valid, :unsupported {
  ...
}

Будет проигнорировано бразуерами, которые не поддерживают :unsupported даже если они поддерживают :valid.

Разница между :is() и :where()

Разница между этими двумя, в том что :is() учитывает спецификацию общего селектора (он принимает специфику своего самого конкретного аргумента), в то же время :where() имеет значение спецификации равное 0. Это можно увидеть на примере на странице документации :where() .

Спецификации

Спецификация Статус Комментарий
Selectors Level 4
Определение ':is()' в этой спецификации.
Рабочий черновик Initial definition

Браузерная совместимость

Update compatibility data on GitHub
КомпьютерыМобильные
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome для AndroidFirefox для AndroidOpera для AndroidSafari on iOSSamsung Internet
:is()Chrome Полная поддержка 68
Замечания Отключено
Полная поддержка 68
Замечания Отключено
Замечания Combinators in the selector list argument may not match correctly (see bug 842157).
Отключено From version 68: this feature is behind the #enable-experimental-web-platform-features preference (needs to be set to Enabled). To change preferences in Chrome, visit chrome://flags.
Нет поддержки 66 — 71
Замечания Альтернативное имя Отключено
Замечания Combinators in the selector list argument may not match correctly (see bug 842157).
Альтернативное имя Использует нестандартное имя: :matches()
Отключено From version 66 until version 71 (exclusive): this feature is behind the #enable-experimental-web-platform-features preference (needs to be set to Enabled). To change preferences in Chrome, visit chrome://flags.
Полная поддержка 12
Замечания Альтернативное имя
Замечания Doesn't support combinators.
Альтернативное имя Использует нестандартное имя: :-webkit-any()
Edge Полная поддержка 79
Замечания Отключено
Полная поддержка 79
Замечания Отключено
Замечания Combinators in the selector list argument may not match correctly (see bug 842157).
Отключено From version 79: this feature is behind the #enable-experimental-web-platform-features preference (needs to be set to Enabled).
Полная поддержка 79
Замечания Альтернативное имя
Замечания Doesn't support combinators.
Альтернативное имя Использует нестандартное имя: :-webkit-any()
Firefox Полная поддержка 78
Полная поддержка 78
Полная поддержка 77
Замечания Отключено
Замечания Enabled by default in Firefox Nightly.
Отключено From version 77: this feature is behind the layout.css.is-where-selectors.enabled preference (needs to be set to enabled). To change preferences in Firefox, visit about:config.
Полная поддержка 4
Замечания Альтернативное имя
Замечания Doesn't support combinators.
Замечания See bug 906353
Альтернативное имя Использует нестандартное имя: :-moz-any()
IE Нет поддержки НетOpera Полная поддержка 55
Замечания Отключено
Полная поддержка 55
Замечания Отключено
Замечания Combinators in the selector list argument may not match correctly (see bug 842157).
Отключено From version 55: this feature is behind the #enable-experimental-web-platform-features preference (needs to be set to Enabled).
Нет поддержки 53 — 58
Замечания Альтернативное имя Отключено
Замечания Combinators in the selector list argument may not match correctly (see bug 842157).
Альтернативное имя Использует нестандартное имя: :matches()
Отключено From version 53 until version 58 (exclusive): this feature is behind the #enable-experimental-web-platform-features preference (needs to be set to Enabled).
Полная поддержка 15
Замечания Альтернативное имя
Замечания Doesn't support combinators.
Альтернативное имя Использует нестандартное имя: :-webkit-any()
Safari Полная поддержка 14
Полная поддержка 14
Полная поддержка 9
Альтернативное имя
Альтернативное имя Использует нестандартное имя: :matches()
Полная поддержка 5
Замечания Альтернативное имя
Замечания Doesn't support combinators.
Альтернативное имя Использует нестандартное имя: :-webkit-any()
WebView Android Полная поддержка ≤37
Замечания Альтернативное имя
Полная поддержка ≤37
Замечания Альтернативное имя
Замечания Doesn't support combinators.
Альтернативное имя Использует нестандартное имя: :-webkit-any()
Chrome Android Нет поддержки 66 — 71
Замечания Альтернативное имя Отключено
Нет поддержки 66 — 71
Замечания Альтернативное имя Отключено
Замечания Combinators in the selector list argument may not match correctly (see bug 842157).
Альтернативное имя Использует нестандартное имя: :matches()
Отключено From version 66 until version 71 (exclusive): this feature is behind the #enable-experimental-web-platform-features preference (needs to be set to Enabled). To change preferences in Chrome, visit chrome://flags.
Полная поддержка 18
Замечания Альтернативное имя
Замечания Doesn't support combinators.
Альтернативное имя Использует нестандартное имя: :-webkit-any()
Firefox Android Полная поддержка 4
Замечания Альтернативное имя
Полная поддержка 4
Замечания Альтернативное имя
Замечания Doesn't support combinators.
Замечания See bug 906353
Альтернативное имя Использует нестандартное имя: :-moz-any()
Opera Android Полная поддержка 48
Замечания Отключено
Полная поддержка 48
Замечания Отключено
Замечания Combinators in the selector list argument may not match correctly (see bug 842157).
Отключено From version 48: this feature is behind the #enable-experimental-web-platform-features preference (needs to be set to Enabled).
Нет поддержки 47 — 50
Замечания Альтернативное имя Отключено
Замечания Combinators in the selector list argument may not match correctly (see bug 842157).
Альтернативное имя Использует нестандартное имя: :matches()
Отключено From version 47 until version 50 (exclusive): this feature is behind the #enable-experimental-web-platform-features preference (needs to be set to Enabled).
Полная поддержка 14
Замечания Альтернативное имя
Замечания Doesn't support combinators.
Альтернативное имя Использует нестандартное имя: :-webkit-any()
Safari iOS Полная поддержка 14
Полная поддержка 14
Полная поддержка 9
Альтернативное имя
Альтернативное имя Использует нестандартное имя: :matches()
Полная поддержка 5
Замечания Альтернативное имя
Замечания Doesn't support combinators.
Альтернативное имя Использует нестандартное имя: :-webkit-any()
Samsung Internet Android Нет поддержки 9.0 — 10.0
Альтернативное имя
Нет поддержки 9.0 — 10.0
Альтернативное имя
Альтернативное имя Использует нестандартное имя: :matches()
Полная поддержка 1.0
Альтернативное имя
Альтернативное имя Использует нестандартное имя: :-webkit-any()
Support for forgiving selector listChrome Нет поддержки НетEdge Нет поддержки НетFirefox Полная поддержка 82IE Нет поддержки НетOpera Нет поддержки НетSafari Нет поддержки НетWebView Android Нет поддержки НетChrome Android Нет поддержки НетFirefox Android Полная поддержка 82Opera Android Нет поддержки НетSafari iOS Нет поддержки НетSamsung Internet Android Нет поддержки Нет

Легенда

Полная поддержка  
Полная поддержка
Нет поддержки  
Нет поддержки
Смотрите замечания реализации.
Смотрите замечания реализации.
Пользователь должен сам включить эту возможность.
Пользователь должен сам включить эту возможность.
Использует нестандартное имя.
Использует нестандартное имя.

Смотрите также