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

这是一个实验中的功能
此功能某些浏览器尚在开发中,请参考浏览器兼容性表格以得到在不同浏览器中适合使用的前缀。由于该功能对应的标准文档可能被重新修订,所以在未来版本的浏览器中该功能的语法和行为可能随之改变。

注意: 在 CSSWG issue #3258 讨论后 :match() 改名为 :is()

The :is() CSS 伪类 函数将选择器列表作为参数,并选择该列表中任意一个选择器可以选择的元素。这对于以更紧凑的形式编写大型选择器非常有用。

注意,许多浏览器通过一个更旧的、带前缀的伪类:any()来支持这个功能,包括旧版本的Chrome、Firefox和Safari。这与:is()的工作方式完全相同,只是它需要厂商前缀,不支持复杂的选择器。

/* 选择header, main, footer里的任意一个悬浮状态的段落(p标签) */
:is(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}

/* 以上内容相当于以下内容 */
header p:hover,
main p:hover,
footer p:hover {
  color: red;
  cursor: pointer;
}


/* 向后兼容的版本:-*-any() 
 (It is not possible to group selectors into single rule,
   because presence of invalid selector would invalidate whole rule.)*/
:-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> )

where
<complex-selector-list> = <complex-selector>#

where
<complex-selector> = <compound-selector> [ <combinator>? <compound-selector> ]*

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

where
<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> ')'

where
<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>? ']'

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

示例

Cross-browser example

<header>
  <p>This is my header paragraph</p>
</header>

<main>
  <ul>
    <li><p>This is my first</p><p>list item</p></li>
    <li><p>This is my second</p><p>list item</p></li>
  </ul>
</main>

<footer>
  <p>This is my footer paragraph</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(':-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() or :any()');
    }
  }
}

for(let i = 0; i < matchedItems.length; i++) {
  applyHandler(matchedItems[i]);
}

function applyHandler(elem) {
  elem.addEventListener('click', function(e) {
    alert('这是一个包含于' + e.target.parentNode.nodeName + '的段落');
  });
}

简化列表选择器

:is() 伪类可以大大简化CSS选择器。例如,下面的CSS:

/* 3-deep (or more) unordered lists use a 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-deep (or more) unordered lists use a 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;
}

但是,不要像下面那么做: (参见 the section on performance 。)

:is(ol, ul, menu, dir) :is(ol, ul, menu, dir) :is(ul, menu, dir) {
  list-style-type: square;
}

Simplifying section selectors

:is 伪类在处理HTML5 sections and headings特别有用。 由于 <section>, <article>, <aside><nav> 经常嵌套在一起, 没有 :is()的话匹配其他元素将会很棘手。

例如, 在没有 :is()的情况下, 在不同深度对所有<h1> 素进行样式化可能非常复杂:

/* Level 0 */
h1 {
  font-size: 30px;
}
/* Level 1 */
section h1, article h1, aside h1, nav h1 {
  font-size: 25px;
}
/* Level 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;
}
/* Level 3 */
/* ... don't even think about it! */

使用 :is()之后,它变的非常简单:

/* Level 0 */
h1 {
  font-size: 30px;
}
/* Level 1 */
:is(section, article, aside, nav) h1 {
  font-size: 25px;
}
/* Level 2 */
:is(section, article, aside, nav)
:is(section, article, aside, nav) h1 {
  font-size: 20px;
}
/* Level 3 */
:is(section, article, aside, nav)
:is(section, article, aside, nav)
:is(section, article, aside, nav) h1 {
  font-size: 15px;
}

Avoiding selector list invalidation

Unlike selector lists, the :is() pseudo-class doesn't get invalidated when one of the selectors passed to it isn't supported by the browser.

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

Will still parse correctly and match :valid even in browsers which don't support :unsupported, whereas:

:valid, :unsupported {
  ...
}

Will be ignored in browsers which don't support :unsupported even if they support :valid.

Notes

any(): — Issues with performance and specificity

Bug 561154 tracks an issue with Gecko where the specificity of :-moz-any() is incorrect. The current (as of Firefox 12) implementation puts :-moz-any() in the category of universal rules, meaning using it as the rightmost selector will be slower than using an ID, class, or tag as the rightmost selector.

For example:

.a > :-moz-any(.b, .c)

... is slower than:

.a > .b, .a > .c

... and the following is fast:

:-moz-any(.a, .d) > .b, :-moz-any(.a, .d) > .c

:is() aims to fix such problems.

Specifications

Specification Status Comment
Selectors Level 4
:is()
Working Draft Initial definition

Browser compatibility

Update compatibility data on GitHub
DesktopMobile
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung Internet
:is()Chrome Full support 68
Notes Disabled
Full support 68
Notes Disabled
Notes Combinators in the selector list argument may not match correctly (see bug 842157).
Disabled From version 68: this feature is behind the Experimental Web Platform Features preference (needs to be set to enabled). To change preferences in Chrome, visit chrome://flags.
No support 66 — 71
Notes Alternate Name Disabled
Notes Combinators in the selector list argument may not match correctly (see bug 842157).
Alternate Name Uses the non-standard name: :matches()
Disabled From version 66 until version 71 (exclusive): this feature is behind the Experimental Web Platform Features preference (needs to be set to enabled). To change preferences in Chrome, visit chrome://flags.
Full support 12
Notes Alternate Name
Notes Doesn't support combinators.
Alternate Name Uses the non-standard name: :-webkit-any()
Edge Full support 79
Notes Disabled
Full support 79
Notes Disabled
Notes Combinators in the selector list argument may not match correctly (see bug 842157).
Disabled From version 79: this feature is behind the Experimental Web Platform Features preference (needs to be set to enabled).
Full support 79
Notes Alternate Name
Notes Doesn't support combinators.
Alternate Name Uses the non-standard name: :-webkit-any()
Firefox Full support 4
Notes Alternate Name
Full support 4
Notes Alternate Name
Notes Doesn't support combinators.
Notes See bug 906353
Alternate Name Uses the non-standard name: :-moz-any()
IE No support NoOpera Full support 55
Notes Disabled
Full support 55
Notes Disabled
Notes Combinators in the selector list argument may not match correctly (see bug 842157).
Disabled From version 55: this feature is behind the Experimental Web Platform Features preference (needs to be set to enabled).
No support 53 — 58
Notes Alternate Name Disabled
Notes Combinators in the selector list argument may not match correctly (see bug 842157).
Alternate Name Uses the non-standard name: :matches()
Disabled From version 53 until version 58 (exclusive): this feature is behind the Experimental Web Platform Features preference (needs to be set to enabled).
Full support 15
Notes Alternate Name
Notes Doesn't support combinators.
Alternate Name Uses the non-standard name: :-webkit-any()
Safari Full support 9
Alternate Name
Full support 9
Alternate Name
Alternate Name Uses the non-standard name: :matches()
Full support 5
Notes Alternate Name
Notes Doesn't support combinators.
Alternate Name Uses the non-standard name: :-webkit-any()
WebView Android Full support ≤37
Notes Alternate Name
Full support ≤37
Notes Alternate Name
Notes Doesn't support combinators.
Alternate Name Uses the non-standard name: :-webkit-any()
Chrome Android No support 66 — 71
Notes Alternate Name Disabled
No support 66 — 71
Notes Alternate Name Disabled
Notes Combinators in the selector list argument may not match correctly (see bug 842157).
Alternate Name Uses the non-standard name: :matches()
Disabled From version 66 until version 71 (exclusive): this feature is behind the Experimental Web Platform Features preference (needs to be set to enabled). To change preferences in Chrome, visit chrome://flags.
Full support 18
Notes Alternate Name
Notes Doesn't support combinators.
Alternate Name Uses the non-standard name: :-webkit-any()
Firefox Android Full support 4
Notes Alternate Name
Full support 4
Notes Alternate Name
Notes Doesn't support combinators.
Notes See bug 906353
Alternate Name Uses the non-standard name: :-moz-any()
Opera Android Full support 48
Notes Disabled
Full support 48
Notes Disabled
Notes Combinators in the selector list argument may not match correctly (see bug 842157).
Disabled From version 48: this feature is behind the Experimental Web Platform Features preference (needs to be set to enabled).
No support 47 — 50
Notes Alternate Name Disabled
Notes Combinators in the selector list argument may not match correctly (see bug 842157).
Alternate Name Uses the non-standard name: :matches()
Disabled From version 47 until version 50 (exclusive): this feature is behind the Experimental Web Platform Features preference (needs to be set to enabled).
Full support 14
Notes Alternate Name
Notes Doesn't support combinators.
Alternate Name Uses the non-standard name: :-webkit-any()
Safari iOS Full support 9
Alternate Name
Full support 9
Alternate Name
Alternate Name Uses the non-standard name: :matches()
Full support 5
Notes Alternate Name
Notes Doesn't support combinators.
Alternate Name Uses the non-standard name: :-webkit-any()
Samsung Internet Android No support 9.0 — 10.0
Alternate Name
No support 9.0 — 10.0
Alternate Name
Alternate Name Uses the non-standard name: :matches()
Full support 1.0
Alternate Name
Alternate Name Uses the non-standard name: :-webkit-any()

Legend

Full support  
Full support
No support  
No support
See implementation notes.
See implementation notes.
User must explicitly enable this feature.
User must explicitly enable this feature.
Uses a non-standard name.
Uses a non-standard name.

相关链接