盤點 CSS Selectors Level 4 中新增的選擇器

NimitzDEV發表於2019-03-02

前言

CSS 選擇器在實踐中是非常常用的,無論是在寫樣式上或是在 JS 中選擇 DOM 元素都需要用到。在 CSS Selectors Level 4 中,工作組繼續為選擇器標準新增了更豐富的選擇器。下面我們來了解一下。

:is()

: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 {
  font-size: 20px;
}
複製程式碼

會發現我們需要寫很長的列表才能區分覆蓋到不同層級中的 h1 標籤,那麼此時 :is 就派上了用場,前面說到,:is即代表著引數裡面的選擇選擇器列表選擇的元素,那麼我們可以把上面的程式碼進行簡化:

/* Level 0 */
h1 {
  font-size: 30px;
}

/* Level 1 */
:is(section, article, aside, nav) h1 {
  font-size: 25px;
}

/* Level 2 */
section :is(section, article, aside, nav) h1 {
  font-size: 20px;
}
複製程式碼

是不是一下子簡潔了很多?是。

:is也可以直接看做是類似選擇列表的語法糖,簡化編寫步驟,瀏覽器會自動將:is展開到簡化之前的形式進行解析。

使用:is時需要注意的

  1. 遇到不支援的選擇器

    通常,在遇到不支援的選擇器時,瀏覽器會直接將整條規則丟棄。例如,當瀏覽器不支援:unsupported時,:supported 是不會生效的。

    :supported, :unsupported {
        font-size: 12px;
    }
    複製程式碼

    而在:is中出現不支援的選擇器,則是相反的行為,:supported 仍然會被正確生效。

    :is(:supported, :unsupported) {
        font-size: 12px;
    }
    複製程式碼
  2. 選擇器的權重

    整個:is選擇器的權重由傳入的選擇器列表中的權重最高的選擇器決定

    :is(span, #id) {
        font-size: 12px;
    }
    複製程式碼

    #id選擇器擁有 (1, 0 ,0) 的權重,而 span 只有 (0, 0, 1),所以最終去匹配 <span></span><div id="id"></p><span id="id"></span>都是使用 (1, 0, 0) 的權重值。

  3. 偽元素不能在:is中使用

瀏覽器支援情況

:is support

這裡查的資料是 :matches:matches 即為 :is 的前身,在 CSS Selector Level 4 中,我們所熟知的:not 也支援選擇器列表作為引數使用了,而功能上:matches則與:not是相對的,所以為了成對,:matches改名為:is

:where()

:where 選擇器是 :is 選擇器的無權重版本。前面提到,:is 的權重是由裡邊的選擇器列表的最高權重決定的,:where 則不關心裡邊的權重,它的權重直接為0。

.class:where(#id) {
    font-size: 12px;
}
複製程式碼

如上面的例子,整個樣式規則權重為 (0, 1, 0),只有 .class 貢獻了權重值。

在未來,:where 選擇器可能會支援指定權重值的選項

:scope

:scope選擇器為它後面的選擇器提供了參考點,在 CSS 中,預設 :scope 代表的即為 :root。而在使用 JavaScript 進行選擇元素時,例如 querySelector 呼叫,可以用來限定選擇器的選擇範圍。

<div class="outer">
  <div class="select">
    <div class="inner">
    </div>
  </div>
</div>
複製程式碼
var select = document.querySelector('.select');
var inner = select.querySelectorAll('.outer .inner');
inner.length; // 1, 不是 0
複製程式碼

你會發現,我本來只想查 .select 裡面的 .outer .inner,這明顯不符合預期,那麼使用 :scope 可以解決此問題。

var select = document.querySelector('.select');
var inner = select.querySelectorAll(':scope .outer .inner');
inner.length; // 0
複製程式碼

:any-link

該選擇器用於選擇所有包含href屬性的連結,在 HTML5 中,這些連結包含 aarea 以及 link 標籤。

:local-link

:local-link:any-link 的作用是相同的,但 :local-link 附加了一個限制,它只能選擇到連結的絕對地址是和當前頁面的域名相匹配的,也就是說,如果一個連結的href是站外連結,將不會被:local-link選擇到。

:target-within

我們都知道,在 URL 中可以用過 #anchor 的形式,讓瀏覽器定位到id#anchor或者nameanchor的錨點上, 當命中一個錨點時,我們可以使用:target選擇到當前命中的那個元素。

現在有一個場景,我的某個section容器的邊框需要在其裡邊的某個錨點命中時改變邊框顏色,此時我們可以對這個容器使用:target-within選擇到這個section,也就是說,這個section內部的某個元素必須能被:target選中。

:focus-within

:focus-within:target-within 的效果是相同的,但它僅在該容器元素內有元素被聚焦時能被選中,也就是說,這個容器內部的某個元素必須能被 :focus 選中。

:focus-visible

當一個元素被聚焦,能被 :focus 選中並且瀏覽器需要在該元素上顯示聚焦效果時(例如瀏覽器中輸入框聚焦時預設顯示的外框),該元素才能被這個選擇器選中。

有了這個選擇器,就能用於自定義聚焦樣式。

:dir()

該選擇器用於根據語言的書寫方向進行選擇,例如常見的左到右書寫形式(left-to-right)則可以使用 :dir(ltr) 進行選擇;右到左的書寫形式則可以使用 :dir(rtl) 進行選擇。如果給定的值是 auto,那麼會選中符合 ltrrlt 順序的元素。

:blank

該選擇器用於選擇輸入框值為空的元素。

:user-invalid

該選擇器用於選擇未通過驗證的輸入框,例如在 maxmin 範圍之外的輸入框,標明瞭required 但值為空的輸入框。

:indeterminate

該選擇器用於選擇狀態未確定的元素,例如在 radiocheckbox 元素中,它們的值可以是是 checked 或者 unchecked,如果沒有顯式地設定,它們的狀態都是未確定的。

時間線相關選擇器

時間線相關的選擇器用於在某些與時間進度相關的功能上使用,例如文字閱讀器閱讀的時間軸,或是在視訊回放中用視訊時間顯示 WebVTT 字幕等。

:current()

當前正在被閱讀器閱讀的元素或正在被顯示的字幕。

article:current(p) {
    background: yellow;
}
複製程式碼

:past()

已經被閱讀過或顯示過的元素。

:future()

將要被閱讀或顯示的元素。

總結

通過豐富選擇器的語法,可以使得我們在實踐中更容易地去選擇元素並確定樣式。同時也能避免一些不必要的hack。

參考連結