CSS Selectors Level 4新特性全面解析

前言

当看到 CSS Selectors Level 4 很多人会理所当然地喊出 CSS4。但是,这里必须明确一个概念,目前所谓的 CSS3 和 CSS4 都是 CSS2.1 以后对某一些 CSS 模块进行升级更新后的称呼。CSS3 和 CSS4 永远都不会出现,它们只是为了区分 CSS 模块升级后的等级,例如有些 CSS 选择器在之前就存在了,但是此时我们为它添加了新的特性,那么这个模块就升级到了 CSS Selectors Level 3 中,如果再一次升级,那么就变成了 CSS Selectors Level 4。下面我们可以对目前 W3C 工作草案中的 CSS Selectors Level 4 新特性进行一个阶段性总结,之所以叫阶段性,是因为未来可能有更多的新特性加入。

Negation pseudo-class——:not()

:not() 用于将符合规则的元素剔除,将样式规则应用于其他元素上。在 CSS3 中已经有 :not(),不过在 CSS3 中只能使用简单的匹配规则,例如 :not(p) 用来选择不是 

 的元素。而在 CSS4 中,可以应用更复杂的匹配规则,但是同样地不允许嵌套使用,例如 :not(:not(...))

.negation {
  color: black;
}

.negation .default:not([data-red="no"]) {
  color: red;
}

.negation .default a {
  color: green;
}

.negation .default a:not([rel="green"], [rel="default"]) {
  color: blue;
}
<div class="negation">
  <div class="default" data-red="no">
    <a href="http://www.baidu.com" rel="green">这里是绿色a>
    <a href="http://www.ele.me" rel="default">这里也是绿色a>
    <a href="http://www.sina.com" rel="blue">这里是蓝色a>
  div>
  <div class="default" data-red="no">
    这里是黑色
  div>
  <div class="default" data-red="yes">
    这里是红色
  div>
div>

:not() 小提示

我们可以利用 :not() 来对 CSS 样式进行一个优先级提升,例如 div:not(span) {…} 跟 div {…} 是同个概念,但是明显地前者的优先级更高。

想解锁更多 :not() 的使用姿势就去看 The Negation Pseudo-class 草案。

Matches-any Pseudo-class——:matches 伪类

:matches() 用于匹配所述规则的元素,并应用相应的样式规则,同样不允许嵌套使用,-webkit-any() 和 -moz-any() 是它的两个兼容性写法。它可以让我们节省书写大量的 CSS 样式匹配规则,让我们从大量重复的规则书写中解放出来。

.matches {
  color: black;
}

.matches :matches(span, div) :matches(span, div) {
  color: green;
}
/*
等同于
.matches span div,
.matches span span,
.matches div span,
.matches div div {
  color: green;
}
 */

.matches :-webkit-any(span, div) :-webkit-any(span, div) {
  color: green;
}

.matches :-moz-any(span, div) :-moz-any(span, div) {
  color: green;
}

.matches :matches(.a, .b) :matches(.a, .b) {
  color: red;
}
/*
等同于
.matches .a .a,
.matches .a .b,
.matches .b .a,
.matches .b .b {
  color: red;
}
 */

.matches :-webkit-any(.a, .b) :-webkit-any(.a, .b) {
  color: red;
}

.matches :-moz-any(.a, .b) :-moz-any(.a, .b) {
  color: red;
}
<div class="matches">
  <span>
    <div>绿色div>
  span>
  <span>
    <span>绿色span>
  span>
  <div>
    <span>绿色span>
  div>
  <div>
    <div>绿色div>
  div>
  <div class="a">
    <div class="b">红色div>
  div>
  <div class="b">
    <div class="a">红色div>
  div>
    <div class="a">
    <div class="a">红色div>
  div>
  <div class="b">
    <div class="b">红色div>
  div>
div>

Case-Sensitivity——不区分大小写匹配标识

Case-Sensitivity 用于声明某个匹配规则中,对字符串或者某个 value 的匹配不区分大小写。该标志声明于 ] 即右中括号之前,例如 [data-value="case" i],其中的 i 就是 Case-Sensitivity 标识。但是如果我们需要明确区分大小写区别的时候,该标识可能会导致某些不可意料的后果,所以使不使用该标识应该明确使用的场景是否对数据来源的大小写敏感。

.case-sensitivity :matches([data-value="case" i]) {
  color: yellow;
}
<div class="case-sensitivity">
  <p data-value='Case'>Casep>
  <p data-value="case">casep>
div>

以上的例子,data-value 虽然既有大写也有小写,但是由于我们声明了 Case-Sensitivity,所以无论大小写都会被匹配。像例子中 caseCaseCASE 等都会被匹配。

The Directionality Pseudo-class——:dir()

:dir() 用于匹配符合某个方向性的元素,例如 :dir(ltr) 和 dir(rtl)。顾名思义,ltr 表示 left to right,即方向从左到右,rtl 表示 right-to-left,即方向从右到左。值得注意的是,使用 :dir() 匹配元素和使用 [dir=...] 在某个程度上是一样的效果,但是一个区别是 [dir=...] 无法匹配到没有显示声明 dir 的元素,但是 :dir() 却可以匹配到由浏览器计算得到或者继承来的 dir 属性的元素,详情可以看一下草案。因此,如果我们有明确地对某个元素声明 dir,那我们大可以使用 [dir=...] 的形式来匹配某个元素,但是如果我们只是单纯从父元素继承而来的 dir,那么此时还是需要用到:dir()

.dir :dir(ltr) {
  color: blue;
}
.dir :dir(rtl) {
  color: green;
}
<div class="dir">
  <p dir="ltr">从左到右p>
  <p dir="rtl">从右到左p>
div>

The Language Pseudo-class——:lang()

:lang() 用于匹配声明了 lang=value 的元素,并且可以使用通配符匹配,例如 p:lang(*-CH) 将可以匹配 de-CH 的 p 元素。

.lang p:lang(de-DE) {
  color: green;
}
.lang p:lang(*-CH) {
  color: blue;
}
<div class="lang">
  <p lang="de-DE-1996">de-DE-1996p>
  <p lang="de-CH">de-CHp>
div>

The Hyperlink Pseudo-class——:any-link 伪类

:any-link 用于匹配带有 href 属性的超链接元素,例如  等带有 href 属性的元素。:-webkit-any-link 和 :-moz-any-link 是它的兼容性写法。目前工作组对该选择器的命名尚不满意,未来该选择器可能会修改其名字。该选择器的作用在于可以选出所有带有链接的元素,如果使用旧方法,那么只能使用标签名的方式或者a[href=value] 的方式去匹配。

.link a:any-link {
  color: red;
}
.link a:-webkit-any-link {
  color: red;
}
.link a:-moz-any-link {
  color: red;
}
<div class="link">
  <a href="#">我是带有颜色的超链接a>
div>

The contextual reference element pseudo-class——:scope

:scope 用于匹配当前作用域下的顶级元素。但是目前