『真香警告』這33個超級好用的CSS選擇器,你可能見都沒見過。

陳大魚頭發表於2020-07-21

前言

CSS 選擇器是 CSS 世界中非常重要的一環。

在 CSS 2 之後,所有的 CSS 屬性都是按模組去維護的。

CSS 選擇器也是如此,然而如今也已經發布了第四版 —— CSS Selectors Level 4 ,這一版最早的草案釋出於2011年09月29日,最後更新是2018年11月21日。

下面讓我們一起來看看 Level 4 新推出的一些選擇器。

正文

下面我們按照型別來劃分

邏輯組合(Logical Combinations)

在這個分類下,我們有以下四個選擇器:

:not()

其實 :not() 不算是新標籤,不過在 Level 4 裡,增加了多選的功能,程式碼如下:

/* 除了.left, .right, .top之外所以的div的盒子模型都會變成flex
*/
div:not(.left, .right, .top) {
  display: flex;
}

/* 等價於 */
div:not(.left), div:not(.right), div:not(.top) {
  display: flex;
}

相容性如下:

not().png

額。。。還不能用

:is()

:is() 偽類將選擇器列表作為引數,並選擇該列表中任意一個選擇器可以選擇的元素。這對於以更緊湊的形式編寫大型選擇器非常有用。

看個栗子:

/* 選擇header, main, footer裡的任意一個懸浮狀態的段落(p標籤) */
:is(header, main, footer) p:hover {
  color: red;
  cursor: pointer;
}

/* 等價於 */
header p:hover,
main p:hover,
footer p:hover {
  color: red;
  cursor: pointer;
}

相容如下:

is().png

:where()

:where() 偽類接受選擇器列表作為它的引數,將會選擇所有能被該選擇器列表中任何一條規則選中的元素。

其實就是跟 :is() ,唯一不同的就是 :where() 的優先順序總是為 0 ,但是 :is() 的優先順序是由它的選擇器列表中優先順序最高的選擇器決定的。

程式碼如下:

<style>
    :is(section.is-styling, aside.is-styling, footer.is-styling) a {
        color: red;
    }

    :where(section.where-styling, aside.where-styling, footer.where-styling) a {
        color: orange;
    }

    footer a {
        color: blue;
    }
</style>
<article>
    <h2>:is()-styled links</h2>
    <section class="is-styling">
        <p>Here is my main content. This <a href="https://mozilla.org">contains a link</a>.
    </section>

    <aside class="is-styling">
        <p>Here is my aside content. This <a href="https://developer.mozilla.org">also contains a link</a>.
    </aside>

    <footer class="is-styling">
        <p>This is my footer, also containing <a href="https://github.com/mdn">a link</a>.
    </footer>
</article>

<article>
    <h2>:where()-styled links</h2>
    <section class="where-styling">
        <p>Here is my main content. This <a href="https://mozilla.org">contains a link</a>.
    </section>

    <aside class="where-styling">
        <p>Here is my aside content. This <a href="https://developer.mozilla.org">also contains a link</a>.
    </aside>

    <footer class="where-styling">
        <p>This is my footer, also containing <a href="https://github.com/mdn">a link</a>.
    </footer>
</article>

:is():where() 對比效果圖如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/where-is-demo.png

相容性如下:

where().png

:has()

:has() 偽類代表一個元素,其給定的選擇器引數(相對於該元素的 :scope)至少匹配一個元素。

:has() 接受一個選擇器組作為引數。在當前規範中 :has() 並未列為實時選擇器配置的一部分,意味著其不能用於樣式表中。

語法如下:

// 下面的選擇器只會匹配直接包含 <img> 子元素的 <a> 元素
a:has(> img)

// 下面的選擇器只會匹配其後緊跟著 <p> 元素的 <h1> 元素:
h1:has(+ p)

相容性如下:

has().png

嗯,全紅。。。

語言偽類(Linguistic Pseudo-classes)

:dir()

:dir()偽類匹配特定文字書寫方向的元素。在HTML中, 文字方向由dir屬性決定。其他的文件型別可能有其他定義文字方向的方法。

:dir() 並不等於使用 [dir=…] 屬性選擇器。後者匹配 dir 的值且不會匹配到未定義此屬性的元素,即使該元素繼承了父元素的屬性;類似的, [dir=rtl][dir=ltr]不會匹配到dir屬性的值為auto的元素。而 :dir()會匹配經過客戶端計算後的屬性, 不管是繼承的dir值還是dir值為auto的。

例子如下:

<style>
    :dir(ltr) {
        background-color: yellow;
    }

    :dir(rtl) {
        background-color: powderblue;
    }
</style>
<div dir="rtl">
      <span>test1</span>
      <div dir="ltr">test2
        <div dir="auto">עִבְרִית</div>
      </div>
</div>

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/dir-demo.png

相容性如下:

dir().png

又是一片紅。。

:lang()

:lang() 偽類基於元素語言來匹配頁面元素。

例子如下:

/* 下例表示選擇文字語言帶有-TN的div元素 (ar-TN, fr-TN). */

div:lang(*-TN) {
    background-color: green
}

瀏覽器支援狀態:沒有一個支援的。

位置偽類(Location Pseudo-classes)

:any-link

:any-link 偽類 選擇器代表一個有連結錨點的元素,而不管它是否被訪問過,也就是說,它會匹配每一個有 href 屬性的 <a><area><link>元素。因此,它會匹配到所有的 :link:visited

例子如下:

<style>
    a:any-link {
        border: 1px solid blue;
        color: orange;
    }

    /* WebKit 核心瀏覽器 */
    a:-webkit-any-link {
        border: 1px solid blue;
        color: orange;
    }
</style>
<a href="https://example.com">External link</a><br>
<a href="#">Internal target link</a><br>
<a>Placeholder link (won't get styled)</a>

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/any-link-demo.png

相容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/any-link.png

:local-link

:local-link偽類可以單獨格式化本地連結(原文是local links)(內部連結)。

例子如下:

a:local-link {
   text-decoration: none;
}

效果 & 相容性

沒有一個瀏覽器是支援的,看不到效果

:target-within

:target-within偽類適用於:target所匹配的元素,以及它DOM節點內所有匹配的元素。

例子如下:

div:target-within {
      border: 2px solid black;
}

效果 & 相容性

沒有一個瀏覽器是支援的,看不到效果

:scope

:scope偽類表示作為選擇器要匹配的作用域的元素。不過目前它等效於 :root

因為尚未有瀏覽器支援CSS的區域性作用域。

例子如下:

:scope {
      background-color: lime;
}

相容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/scope.png

瀏覽器演算法不支援,相容有跟沒沒區別~

使用者行為偽類(User Action Pseudo-classes)

:focus-visible

當元素匹配 :focus 偽類並且客戶端(UA)的啟發式引擎決定焦點應當可見(在這種情況下很多瀏覽器預設顯示“焦點框”。)時,:focus-visible 偽類將生效。

這個選擇器可以有效地根據使用者的輸入方式(滑鼠 vs 鍵盤)展示不同形式的焦點。

例子如下:

<style>
    input, button {
        margin: 10px;
    }

    .focus-only:focus {
        outline: 2px solid black;  
    }

    .focus-visible-only:focus-visible {
        outline: 4px dashed darkorange;
    }
</style>
<input value="Default styles"><br>
<button>Default styles</button><br>
<input class="focus-only" value=":focus only"><br>
<button class="focus-only">:focus only</button><br>
<input class="focus-visible-only" value=":focus-visible only"><br>
<button class="focus-visible-only">:focus-visible only</button>

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/focus-visible-demo.gif

相容性如下:

目前只有Chrome 67+ 相容...

:focus-within

:focus-within偽類適用於:focus所匹配的元素,以及它DOM節點內所有匹配的元素。

例子如下:

<style>
    form {
        border: 1px solid;
        color: gray;
        padding: 4px;
    }

    form:focus-within {
        background: #ff8;
        color: black;
    }

    input {
        margin: 4px;
    }
</style>

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/focus-within-demo.gif

時間尺寸偽類(Time-dimensional Pseudo-classes)

:current && :past && :future

這個偽類選擇器會選擇HTML5<video>的語言渲染以及播放過程中的時間維度相對元素。所有相關的選擇器都像:matches()。這幾個偽類選擇器的區別在於:past會選擇:current所選的元素之前的所有節點。所以,:future就是指之後的所有節點了。

例子如下:

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


/* Past */
:past,
/* Future */
:future {
      display: none;
}

相容性如下:

目前沒有任何瀏覽器支援

輸入偽類(The Input Pseudo-classes)

:read-only:read-write

:read-only偽類選擇器表示當前元素是使用者不可修改的。

:read-write偽類選擇器表示當前元素是使用者可修改的。這個偽類選擇器可以使用在一個可輸入的元素或 contenteditable 元素(HTML5 屬性)。

例子如下:

<style>
    :read-only {
      font-size: 20px;
      color: green;
    }

    :read-write {
      border: 1px solid orange;
      font-size: 18px;
    }
</style>
<input type="text" placeholder='text here'>
<input type="tel" placeholder='number here'>
<select>
      <option>1</option>
      <option>2</option>
</select>

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/read-only-write-demo.png

相容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/read-only-write.png

:placeholder-shown

:placeholder-shown 偽類 在 <input><textarea> 元素顯示 placeholder text 時生效。

例子如下:

<style>
    input {
        border: 2px solid black;
        padding: 3px;
    }

    input:placeholder-shown {
        border-color: silver;
    }
</style>
<input placeholder="Type something here!">

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/placeholder-shown-demo.png

相容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/placeholder-shown.png

:default

:default 偽類選擇器 表示一組相關元素中的預設表單元素。

該選擇器可以在 <button>, <input type="checkbox">, <input type="radio">, 以及 <option> 上使用。

例子如下:

<style>
    input:default {
          box-shadow: 0 0 2px 1px coral;
    }

    input:default + label {
          color: coral;
    }
</style>
<input type="radio" name="season" id="spring">
<label for="spring">Spring</label>

<input type="radio" name="season" id="summer" checked>
<label for="summer">Summer</label>

<input type="radio" name="season" id="fall">
<label for="fall">Fall</label>

<input type="radio" name="season" id="winter">
<label for="winter">Winter</label>

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/default-demo.png

相容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/default.png

:indeterminate

:indeterminate 偽類選擇器表示狀態不確定的表單元素。

它支援:

  • <input type="checkbox"> 元素,其 indeterminate 屬性被JavaScript設定為 true
  • <input type="radio"> 元素, 表單中擁有相同 name值的所有單選按鈕都未被選中時。
  • 處於不確定狀態的 <progress> 元素

例子如下:

<style>
    input, span {
        background: red;
    }

    :indeterminate, :indeterminate + label {
        background: lime;
    }
    progress {
          margin: 4px;
    }
    progress:indeterminate {
          opacity: 0.5;
          background-color: lightgray;
          box-shadow: 0 0 2px 1px red;
    }
</style>
<div>
    <input type="checkbox" id="checkbox">
    <label for="checkbox">Background should be green</label>
</div>
<br />
<div>
    <input type="radio" id="radio">
    <label for="radio">Background should be green</label>
</div>
<br />
<progress></progress>
<script>
    'use strict'
    const inputs = document.querySelectorAll('input')
    inputs.forEach(input => {
        input.indeterminate = true
    })
</script>

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/indeterminate-demo.gif

相容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/indeterminate.png

:valid:invalid

判斷有效性的偽類選擇器(:valid:invalid)匹配有效或無效,<input><form>元素。

:valid偽類選擇器表示值通過驗證的<input>,這告訴使用者他們的輸入是有效的。

:invalid偽類選擇器表示值不通過通過驗證的<input>,這告訴使用者他們的輸入是無效的。

例子如下:

<style>
    input:valid {
        outline: 1px solid green;
    }

    input:invalid {
        outline: 1px solid red;
    }
</style>
輸入文字:
<input type="text" pattern="[\w]+" required />
<br />
輸入電話號碼:
<input type="tel" pattern="[0-9]+" required />

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/valid-demo.gif

相容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/valid.png

:in-range:out-of-range

如果一個時間或數字<input>具有maxmin屬性,那麼:in-range會匹配到輸入值在指定範圍內的<input>:out-of-input則匹配輸入值不在指定範圍的<input>。如果沒有規定範圍,則都不匹配。

例子如下:

<style>
    li {
        list-style: none;
        margin-bottom: 1em;
    }

    input {
        border: 1px solid black;
    }

    input:in-range {
        background-color: rgba(0, 255, 0, 0.25);
    }

    input:out-of-range {
        background-color: rgba(255, 0, 0, 0.25);
        border: 2px solid red;
    }

    input:in-range + label::after {
        content: 'okay.';
    }

    input:out-of-range + label::after {
        content: 'out of range!';
    }
</style>
<form action="" id="form1">
    <ul>Values between 1 and 10 are valid.
        <li>
            <input id="value1" name="value1" type="number" placeholder="1 to 10" min="1" max="10" value="12">
            <label for="value1">Your value is </label>
        </li>
    </ul>
</form>

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/in-out-range-demo.gif

相容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/in-out-range.png

:required:optional

偽類選擇器:required:optional匹配了<input><select>, 或 <textarea>元素。

:required表示“必填”

:optional表示“可選”

例子如下:

<style>
    input:required {
        border: 1px solid orange;
    }
    input:optional {
        border: 1px solid green;
    }
</style>
必填的:<input type="text" required>
<br />
可選的:<input type="text">

效果如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/requirement-demo.png

相容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/optional.png

:required 的相容性在上面有。

:blank

:blank 偽類選擇器 用於匹配如下節點:

  1. 沒有子節點;
  2. 僅有空的文字節點;
  3. 僅有空白符的文字節點。

有點類似於:empty,但是比:empty寬鬆,目前還是沒有任何一款瀏覽器支援。

:user-invalid

:user-invalid偽類選擇器匹配輸入錯誤的元素。不過跟其它的輸入偽類不同的是,它僅匹配使用者輸入時的錯誤,而不是靜默狀態下的錯誤,這樣就會比較人性化,可惜,目前還是沒有任何一款瀏覽器支援。

樹型偽類(Tree-Structural pseudo-classes)

:nth-child:nth-last-child

:nth-child:nth-last-child並不是 Level 4 才推出的偽類選擇器,但是在 Level 4 裡 新增了在元素組裡匹配的功能。

語法如下::nth-child/nth-last-child(An + B [of S] ?)

例子如下:

:nth-child(-n+3 of li.important)

上面的例子通過傳遞選擇器引數,選擇與之匹配的第n個元素,這裡表示li.important中前三個子元素。

它跟以下規則不同:

li.important:nth-child(-n+3)

這裡表示的時候如意前三個子元素剛才是li.important時才能被選擇得到。

相容性如下:

https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/img/css/selectors-4/list-nth-child.png

(魚頭注:牛皮,Safari居然彎道超車了,不過別的瀏覽器不支援,也沒啥用...)

網格選擇器(Grid-Structural Selectors)

||

|| 組合器選擇屬於某個表格行的節點。

例子如下:

<style>
    col.selected || td {
          background: gray;
          color: white;
          font-weight: bold;
    }
</style>
<table border="1">
      <colgroup>
            <col span="2"/>
            <col class="selected"/>
      </colgroup>
      <tbody>
            <tr>
                  <td>A
                  <td>B
                  <td>C
            </tr>
            <tr>
                  <td colspan="2">D</td>
                  <td>E</td>
            </tr>
            <tr>
                  <td>F</td>
                  <td colspan="2">G</td>
            </tr>
      </tbody>
</table>

上面的例子可以使C,E 與 G單元格變灰。

很可惜,目前還是沒有任何瀏覽器給予支援。

:nth-col() :nth-last-col()

偽類選擇器:nth-col() :nth-last-col()表示選擇正向或反向的表格行的節點。

語法和:nth-child:nth-last-child類似,只不過它是選擇表格內的元素。

目前還是沒有任何瀏覽器支援。

最後

總結

以上便是CSS選擇器 Level 4 裡新出的所有選擇器,其實都是非常有用的,雖然有些選擇器的瀏覽器支援度並不樂觀的。

希望各大瀏覽器廠商可以趕快增加對它們的支援吧。

參考資料

  1. can i use
  2. MDN
  3. Selectors Level 4 W3C Working Draft

相關文章