[CSS] Selector Level 4 搶先看

雖然 CSS Selector Level 4 目前還在草稿階段,不過俗話說的好,別讓您的孩子輸在起跑點上,所以趁現在偷跑也是很合理的。

另外,我贊成讓孩子輸在起跑點上。

Selector Level 4

http://dev.w3.org/csswg/selectors4/

我說過了,他目前還是 Editor's Draft,所以,是不是裡面所有的 Selector 將來都會出現?我不敢保證。在這裡我也不打算全部都拿出來講,不然你就去看原文就好了,也不用看我在這邊練肖喂(台語

  • 增加了一狗票 Pseudo-classes
    • Negation pseudo-class
    • Matches-Any pseudo-class
    • The :dir pseudo-class
    • The :lang pseudo-class
    • The hyperlink pseudo-class
    • The local link pseudo-class
    • The scope pseudo-class
    • Time-dimensional pseudo-classes
    • The drag-and-drop pseudo-classes
    • The mutabillity pseudo-classes
    • The placeholder pseudo-class
    • The default option pseudo-class
    • The indeterminate-value pseudo-class
    • The validity pseudo-classes
    • The range pseudo-classes
    • The optionality pseudo-classes
    • Structural pseudo-classes
    • Grid-Structural pseudo-classes
  • 增加了邏輯與組合子的選擇器
    • Reference combinator
    • Column combinator
    • Determining the subject of a selector + Child combinator
  • 增修結構、屬性與元素選擇器
    • Attribute selectors: Case-sensitivity

擬似類別大亂鬥

Pseudo-classes(擬似類別,在 Level 4 之後簡直是群魔亂舞!有些雖然是舊瓶新酒,不過老實說我也不知道為什麼要重新定義一次(像是 E:dir(ltr) 這種在 Level 2 曾經出現過的東西。

Negation pseudo-class

E:not(s1[, s2, ...])

這個東西在 Level 3 就出現過,但是現在可以連續寫多組 Selectors 在裡面,在 Level 3 只能寫一組。另外,她不能跟 :matches 併用,也不能否定自己跟自己併用,也就是說,底下的寫法是無效的,

/* 這是無效的 */
E:not(:not(F))

/* 這樣也會無效 */
E:matches(:not(F))

Matches-Any pseudo-classes

E:matches(s1[, s2, ...])

跟 Negation 剛好相反,他是幫你取出任何符合條件的選擇器。另外,跟 :not 或是多數擬似類別一樣,不能使用組合子開頭(嗯?該不會沒有人知道這件事情!?

同樣的,他也不能跟 :not 或是自己併用,

/* 這是無效的 */
E:matches(:matches(F))

/* 這樣也會無效 */
E:not(:matches(F))

:dir, :lang pseudo-classes

不解釋!

The hyperlink pseudo-class

:any-link

這個選擇器有特殊條件,任何在 HTML5 中的 <a>, <area><link> 標簽,包含 href 屬性的,都符合這個擬似類別選擇器的條件。但是官方給了一個特別的 ISSUE,

ISSUE 6 Any better name suggestions for this pseudo?

這我就不解釋了(個人覺得蠻雞肋的這個

The local link pseudo-class

:local-link {
    /* declarations */
}

:local-link(n) {
    /* declarations */
}

這東西就神了,這個選擇器的意思是,解析你的 URL,但是只拿你的 Path 的部分,舉個例子來說,

:local-link {
    /* 只要是你站內的畫面全部生效 */
}

:local-link(0) {
    /* 當瀏覽到 http://blog.hinablue.me/im/about.html 時生效 */
}

:local-link(1) {
    /* 當瀏覽到 http://blog.hinablue.me/im/hina/about.html 時生效 */
}

:local-link(2) {
    /* 當瀏覽到 http://blog.hinablue.me/im/hina/chen/about.html 時生效 */
}

nav :local-link {
    /* 這是官方提出的範例,意思是,當你的網址是 Navigation list 時生效 */
    /* 但是,這個東西瀏覽器要實作感覺挺討人厭的(稱讚意味 */
}

看出端倪了嗎?意思就是,以 / 來分割你的 URL,然後從 domain name 那邊開始往後算,一直到最後一個,分別就是 :local-link 的順序,所以,你可以在不同的路徑切換不同的樣式。

The scope pseudo-class

:scope {
    /* If reference element set is empty :scope equivalent to :root */
}

E:scope {
}

這個擬似類別很難解釋,而且其實他 Level 3 就有了。基本上官方解釋我也有看沒有懂,先附上原文,

The :scope pseudo-class represents any element that is in the reference element set. This is is a (potentially empty) set of elements that provide a reference point for selectors to match against, such as that specified by the querySelector() call in SELECTORS-API2, or the parent element of a scoped <style> element in HTML5.

If the reference element set is not explicitly specified, it defaults to representing the scoping root (if any), else represents the root of the document (i.e. matches :root). Specifications intending for this pseudo-class to match specific elements rather than the document's root element must define either a scoping root (if using scoped selectors) or an explicit reference element set.

意思就是呢,使用 :scope 這個擬似類別,就是將這個元素或類別設定為參考元素集(reference element set,它提供 querySelector 或是 scoped <style> element 一個參考點。我知道這樣講跟天書沒兩樣,所以舉個例子,

document.querySelector('img', [list-of-links]);

意思就是,我要查找有鏈結的圖片,但是呢,如果我不給 [list-of-links],他會從整個 document 開始找起(因為等同於 :root 這還牽扯到了 Scoped SelectorsRelative Selectors 還有如何轉換一個 Absolutizing Selector 的事情。

這個選擇器大部分跟瀏覽器實作,還有 SELECTOR API 層有關,所以目前沒有實際的操作方式(瀏覽器也沒有支援,所以看不出來他對元素操作上有什麼影響。

Time-dimensional pseudo-classes

這個選擇器跟 <video> 沒關係,只是很像是在操作影片的概念而已。他的擬似類別有這些,

  • :current
  • :past
  • :future
:current {
    /* declarations */
}

:current(s1[, s2, ...]) {
    /* declarations */
}

:past {
    /* declarations */
}

:future {
    /* declarations */
}

意思是,當前顯示的元素,就會符合 :current 這個選擇器,而 :past:future 有先決條件,必須要是緊鄰元素(sibling elements,舉個例子來說,假設你有一個橫向捲軸輪播,放第一張的時候就是 :current,第二張就是 :future,然後沒有 :past

當你播放第二張時,第一張就是 :past,第二張就是 :current,然後第三張就是 :future 這樣。

The drag-and-drop pseudo-classes

E:drop {
    /* declarations */
}

E:drop( [active || valid || invalid]? ) {
    /* declarations */
}

這是由於 HTML5 支援 Drag-And-Drop 的關係,所衍生出來的擬似類別。他也是可程式化的擬似類別之一,

  • :drop() 等同於 :drop 符合所有 dropped 事件。
  • :drop( active ) 當 drag 在這個 drop 目標時符合這個選擇器。
  • :drop( [valid || invalid] ) 在 HTML5 中可以定義 dropzone 這個屬性,也就是說,如果 drop 目標屬於(或不屬於)這個 drop 選擇器,會觸發這個選擇器事件。
  • :drop( valid active ) 上述兩個方法可混用。

The mutabillity pseudo-classes

E:read-only

E:read-write

用於 <input> 不解釋。

The placeholder pseudo-class

E:placeholder-shown

用於任何擁有 placeholder 屬性元素,不解釋。

The default option pseudo-class

E:default

用於 <select> 元素中,當 <option> 使用 default 時(本來想不解釋

The indeterminate-value pseudo-class

E:indeterminate

這是一個很神奇的東西,他可以指定任何一個元素在不確定狀態下,所能使用的樣式。例如 <input> 標簽的 type 在更動 radiocheckbox 的時候,或是一個 progress 在初始值未知的狀態下。

老實說,我想不到這能幹嘛(遮臉

The validity pseudo-classes

E:valid {
    /* declarations */
}

E:invalid {
    /* declarations */
}

用在表單元件的擬似類別,HTML5 可以支援表單檢查(你知道的

The range pseudo-classes

E:in-range {
    /* declarations */
}

E:out-of-range {
    /* declarations */
}

同上,在使用 <input>type="range" 的時候所使用。

The optionality pseudo-classes

E:required {
    /* declarations */
}

E:optional {
    /* declarations */
}

一樣是使用在表單元件。

Structural pseudo-classes

E:blank {
    /* declarations */
}

E:nth-match(s1[, s2, ...]) {
    /* declarations */
}

E:nth-last-match(s1[, s2, ...]) {
    /* declarations */
}

這三組是在 Level 4 新增的,

  • :blank 可以符合空元素或是空白(whitespace
  • :nth-match 類似 :matches:nth-child 的合體
  • :nth-last-match 同上,與 :nth-last-child 合體

Grid-Structural pseudo-classes

E:nth-column(s1[, s2, ...]) {
    /* declarations */
}

E:nth-last-column(s1[, s2, ...]) {
    /* declarations */
}

這是搭配 <col> 標籤所使用的,與 :nth-child 類似。

新的組合子

最讓我興奮的應該是那個 /foo/ 而已吧,還有 || 很神奇這樣。至於那個 ! 老實說,可以奸巧巧妙的解決父子元素的一些問題。

Reference combinator

E /foo/ F

這當中我應該最喜歡這個!舉個例子來說,

label /for/ input {
    border: 1px solid red;
}

意思就是說呢,在 <input> 標籤加上 border: 1px solid red;,當 <label> 標籤有 for 屬性,且該 <input> 擁有該屬性所指定的 ID 的時候。換句話說,我也可以這樣做,

.box /data-target/ .item {
    border: 1px solid red;
}
<div class="box" data-target="mychild">
  <div class="box" id="mychild"></div>
</div>

Column combinator

E || F

你可以把它想成是一個陣列,在這個選擇器列表中的元素都會發生作用。

Determining the subject of a selector + Child combinator

!E > F

這個頗難解釋,但是依照 CSS 的讀取方式來看會比較容易理解(由右到左(什麼?你不知道!

ol > li {
    /* 有 li 子元素被包含在 ol 元素底下 */
}

!ol > li {
    /* 有一個 ol 元素,擁有 li 子元素 */
}

!div > !p.warning {
    /* 所有的 div 元素,包含所有 p.warning 類別的元素,且包含於 div 元素底下 */
}

這些事情看起來是一樣(感覺像是繞口令,但是,實作上會有些微的差異。以第三個例子來說,

<div>
    /* 這裡有效 */
    <p class="warning">
    </p>
    <div>
        /* 這裡有效 */
        <p class="warning">
        </p>
    </div>
    <p>
    </p>
</div>

注意我標記 這裡有效 的位置,是在 <div> 元素,而不是 <p class="warning"> 元素上,這就是差別。他會將樣式套用在所屬的父元件上面,而不是 Child-combinator 的子元件上面。

屬性上的新操作

其實有點老梗,就是 Case-sensitivity 而已(翻白眼

Attribute selectors: Case-sensitivity

input[title="hello" i]

注意後面那個 i(你懂我的明白

小結

雖然 Selector Level 4 看起來好像沒有 Media Query Level 4 那麼樣的變態精彩,但是我想還是有很多東西可以期待一下,畢竟前端這條路好像越來越難走了,有這些便利的工具(或是方法,對我們來說也不是壞事。

可是好像回家種田比較實在一點就是(喂

Hina Chen
偏執與強迫症的患者,算不上是無可救藥,只是我已經遇上我的良醫了。
Taipei