1. 程式人生 > >CSS Selectors Level 4新特性全面解析

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) 用來選擇不是 <p></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 {…} 是同個概念,但是明顯地前者的優先順序更高。

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'>Case</p>
  <p data-value="case">case</p>
</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-1996</p>
  <p lang="de-CH">de-CH</p>
</div>

The Hyperlink Pseudo-class——:any-link 偽類

:any-link 用於匹配帶有 href 屬性的超連結元素,例如 <a><area><link> 等帶有 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 用於匹配當前作用域下的頂級元素。但是目前 <style scoped> 已經被移除——issue,所以 :scope 基本等效於:root

<div class="scope">
  <p>This paragraph is outside the scope.</p>
  <div>
    <style scoped>
      :scope {
        background-color: red;
      }
      p {
        color: blue;
      }
    </style>
    <p>This paragraph is inside the scope.</p>
  </div>
</div>

以上程式碼,第二個 div 將會有紅色背景,並且他的所有 <p> 子元素都將擁有藍色文字。

Time-dimensional Pseudo-classes——:current(), :past(), :future()

我個人用 時間軸偽類 統一稱呼 :current():past():future() 這三個偽類。:current() 匹配時間軸當前的元素,:past() 匹配 :current()元素之前的元素,:future() 則匹配當前時間軸後的所有元素。這裡說的時間軸指的是例如WebVTT。值得注意的是,規範中寫道如果使用的時間軸並不是文件語言所規定的,那麼 :past() 和 :future() 有可能分別匹配 :current() 元素的前面的兄弟元素和後面的兄弟元素。由於在 Chrome Canary 和 Safari TP 上都不支援這幾個偽類,所以無法實驗正確性。下面使用的例子是從這個網址摘過來的。

:current(p, span) {
  background-color: yellow;
}

:past(p, span),
:future(p, span) {
  background-color: gray;
}
<video controls preload="metadata">
  <source src="http://html5demos.com/assets/dizzy.mp4" type="video/mp4" />
  <source src="http://html5demos.com/assets/dizzy.webm" type="video/webm" />
  <source src="http://html5demos.com/assets/dizzy.ogv" type="video/ogv" />

  <track label="English" kind="subtitles" srclang="en" src="http://www.iandevlin.com/html5test/webvtt/upc-video-subtitles-en.vtt" default>
</video>

The Indeterminate-value Pseudo-class——:indeterminate

在 radio 和 checkbox 元素上一般有兩種狀態——選中 和 未選中,但是有的時候的狀態會是不確定狀態,而:indeterminate 就是匹配這種不確定狀態的 radio 或 checkbox

:indeterminate + label {
  background-color: gray;
}
<input type="radio" name="name" id="test">
<label for="test">未確定狀態</label>

通常地,radio 和 checkbox 在沒有宣告選中狀態時,預設只有兩種可能性:checked 和 unchecked,為了讓他們出現第三種狀態,我們可以藉助 JS 來控制:

document.querySelector('#test').indeterminate = true;

上面例子的 <label> 在 <input> 處於 indeterminate state 的時候,文字將會變為灰色。

The default-option pseudo-class——:default

:default 匹配一組相似元素集合中的預設元素,例如 <form> 中有多個 <input>,其中有一個是 <input type="submit">,那麼該元素將會被匹配。此外還有 <option> 也有預設元素。

.default .default-form :default {
  background-color: gray;
}
<div class="default">
  <form class="default-form" action="#" method="get">
    <input type="submit" name="name" value="submit">
    <input type="reset" name="name" value="reset">
  </form>
</div>

The validity pseudo-classes——:valid, :invalid

在 <input type="email"> 中,如果我們輸入了 abc123,那麼此時 :invalid 將會匹配該元素,假如我們輸入[email protected],那麼此時 :valid 將會匹配該元素。這裡要注意假如我們沒有為 <input> 作約束,例如<input type="text">,那麼它的任意輸入將使元素既不會被 :valid 匹配,也不會被 :invalid 匹配。

.valid input:valid {
  color: green;
}

.valid input:invalid {
  color: red;
}
<div class="valid">
  <input type="email" name="eamil_valid" value="[email protected]">
  <input type="email" name="email_invalid" value="abc">
</div>

The range pseudo-classes——:in-range, :out-of-range

:in-range 和 :out-of-range 只對有被條件約束的元素起作用,例如 <input type="number" min="1" value="1">,如果輸入數字小於 1,那麼將會被 :out-of-range 匹配,反之則是被 :in-range 匹配。在很多時候,我們需要對“髒值”做一個高亮的顯示,以前可能需要配合 JS 對值的邊界進行檢測,然後在對元素的樣式進行修改。而現在,有了這兩個偽類的存在,我們可以完全使用 CSS 來控制。

.range input<