:is

Avatar of Geoff Graham
Geoff Graham on

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 价值 $200 的免费积分!

CSS 中的伪选择器 :is() 允许您以更简洁的方式编写复合选择器。 例如,而不是写

ul li,
ol li {}

我们可以写

:is(ul, ol) li {}

这可以快速完成否则非常冗长、复杂且容易出错的选择器。 看

:is(section, article, aside, nav) :is(h1, h2, h3, h4, h5, h6) {
  color: #BADA55;
}

/* ... which would be the equivalent of: */
section h1, section h2, section h3, section h4, section h5, section h6, 
article h1, article h2, article h3, article h4, article h5, article h6, 
aside h1, aside h2, aside h3, aside h4, aside h5, aside h6, 
nav h1, nav h2, nav h3, nav h4, nav h5, nav h6 {
  color: #BADA55;
}

您可以像预期的那样将伪选择器附加到元素。 比如当元素具有两个类中的任何一个时,选择特定类型的元素

div:is(.cool, .fun) {
  color: red;
}

/*
<div class="cool">match</div>
<div class="fun">match</div>
<p class="fun">not match</p>
*/

嘿,这不像 CSS 预处理吗?

使用 :is() 简化选择器类似于 CSS 预处理器处理嵌套规则的方式

/* SCSS written like this: */
div, p, ul, ol {
  span {
    /* ... */
  }
}

/* after processing becomes: */
div span, p span, ul span, ol span {
  /* ...*/
}

/* which is a lot like the effect of :is()! */

但要注意! 像 Sass 这样的预处理器将“展开”您的嵌套规则,形成一个易于理解的选择器列表。 :is() 将以略微不同的方式处理特异性规则。

:is() 的特异性

根据 CSS4 工作草案

:is() 伪类的特异性被其最具体参数的特异性所取代。 因此,使用 :is() 编写的选择器并不一定具有与不使用 :is() 编写的等效选择器相同特异性。

这意味着 :is() 的特异性会自动升级到提供的参数列表中最具体的项目

/* This has higher precedence... */
:is(ol, .list, ul) li { /* ... */ }

/* ...than this, even though this is later... */
ol li  { /* ... */ }

/* ...because :is() has the weight of it's heaviest selector, which is `.list`! */

宽容的选择器列表

通常,如果选择器的任何部分无效,则整个块将被抛出

p, p::not-real {
  color: red; /* nothing will be red, as ::not-real is an invalid selector */
}

我听说浏览器将来可能会对此放宽,但我们还没有达到那个阶段。 如果您希望保留该功能并且不必将其拆分为两个单独的块,is() 可以提供帮助,因为它很“宽容”

:is(p, p::not-real) { /* this is fine */
  color: red;
}

当我想到无效的逗号分隔选择器时,我总是想到 ::selection::-moz-selection 供应商前缀版本,但是……

:is(::selection, ::-moz-selection) { /* this doesn't work in Chrome for some reason 🤷‍♀️ */
  background: yellow;
}

浏览器支持

这些浏览器支持数据来自 Caniuse,其中有更多详细信息。 数字表示浏览器在该版本及更高版本中支持该功能。

桌面

ChromeFirefoxIEEdgeSafari
88788814

移动设备/平板电脑

Android ChromeAndroid FirefoxAndroidiOS Safari
12712712714.0-14.4

为了获得最佳支持,您可能还想查看使用 :matches(使用供应商前缀 :any 填补一些空白)以实现一般功能。 并且,:not() 是另一个可以帮助匹配的伪类。

有趣的是,:is():matches 之后引入,而 :matches:any 之后引入。 就像 :any:matches 替代,而 :matches:is() 替代一样,细节在不断变化。 看到这些东西如何演变总是很酷。

要获得对“匹配任何”的最大支持,需要使用历史名称的混合,因为浏览器的处理目前是供应商前缀和实验设置的混合体。

/* These are deprecated, but still necessary in some browsers: */
:-moz-any(div, p) > em { /* ... */ }
:-webkit-any(div, p) > em { /* ... */ }

/* Has been replaced by :is() in CSS4, but still supported 
by some browsers with experimental features enabled */
:matches(div, p) > em { /* ... */ }

/* Latest syntax */
:is(div, p) > em { /* ... */ }

历史

最初,这个伪类被命名为 :any(),并且仅在有限的供应商特定支持下实现

/* Never actually worked */
:any(div, p) > em { /* ... */ }

然后在 CSS4 工作草案的早期版本中将“匹配任何”伪类的名称更改为 :matches(),并对某些浏览器提供额外的(不完整的)支持。

/* Sort of works */
:matches(div, p) > em { /* ... */ }

“匹配任何”选择器的目标是使复杂的选择器分组更容易编写,这正是我们使用 :is() 获得的,而且更多。

更多信息