提升你的 CSS 選擇器技能
小編推薦: ofollow,noindex">掘金是一個面向程式員的高質量技術社群,從 一線大廠經驗分享到前端開發最佳實踐,無論是入門還是進階,來掘金你不會錯過前端開發的任何一個技術乾貨。
我已經使用CSS多年了,但直到最近我還沒有深入研究過關於 CSS 選擇器的主題。
為什麼我需要學習 CSS 選擇器呢? 我們現在知道了所有的內部選擇器了嗎?
問題是(至少對我來說是這樣)隨著時間的推移,很容易習慣在每個專案上使用相同的習慣的選擇器集合來完成你要做的事情。
因此,我自己對 CSS 選擇器知識進行了深入的審查,並發現了一些有趣的內容,這些內容對我來說是新的,或者是以前我從來沒有想過這些使用方式。
我還發現了一些很酷的新選擇器,將來可用,但還沒有廣泛使用。
我們一起來深入研究一下各種型別的 CSS 選擇器吧。 您在日常工作中已經使用了,或者本文沒涉及到的 CSS 選擇器技能歡迎留言告訴我。
準備好提升你的 CSS 選擇器技能了嗎?我們一起 GO!
組合選擇器
讓我們從熟悉的選擇器開始。組合選擇器用於選擇子元素和兄弟元素,並且相信大家已經使用了很長一段時間了吧。
A B A > B A + B A ~ B
您應該熟悉相鄰兄弟元素選擇器 A + B
,他會選擇緊跟 A 的 B 元素。但是一般兄弟元素選擇器 A~B
呢? 他將選擇跟隨 A 的所有兄弟 B 元素:
以下是例項:
See the Pen 組合選擇器 Combinator Selectors by feiwen8772 ( @feiwen8772 ) on CodePen .0
第二行 New York 行被選中是因為它緊跟在第一行之後 table tbody tr:first-child + tr
,並且最後兩個城市被高亮顯示,因為他們被一般兄弟選擇器 table tbody tr:nth-child(4) ~ tr
匹配,也就是第四行之後的所有行。
屬性選擇器
我非常喜歡屬性選擇器。當您需要將包含某個屬性的元素與特定值匹配時,它們可以非常靈活。
See the Pen Attribute Selectors #1 by David Gwyer ( @dgwyer ) on CodePen .0
此示例演示如何選擇所有複選框元素並將樣式應用於其匹配標籤,以使其變為粗體和藍色。
然後,我們覆蓋具有特定名稱的 chk2
複選框的樣式,並將其匹配的標籤著色為紅色。 請注意其他表單元素標籤如何不受影響且未應用標籤樣式。
屬性選擇器不僅適用於表單元素,它們還可以定位任何元素的屬性。 您可以匹配任何屬性,而不僅僅是官方支援的屬性。 此外,您可以檢查屬性是否存在,如下所示:
button[icon]
這匹配包含 icon
屬性的 <button>
元素。它將匹配 icon
屬性,無論 icon
屬性是空值還是設定為特定值。 更多例子:
See the Pen Attribute Selectors #2 by David Gwyer ( @dgwyer ) on CodePen .0
第一個連結沒有 target
屬性,因此不匹配。 接下來的兩個連結是匹配的,因為它們的 target
屬性具有空值或特定值的屬性。 最後,最後一個連結設定為粉紅色,因為它 fluffy
屬性匹配。 它的值無關緊要,只需要與 a[fluffy]
選擇器相匹配即可。
一個實際的例子可能是突出顯示沒有alt屬性的影象。 此屬性對於網頁的可訪問性來說是所必需的,因此對於SEO而言,確保所有影象元素都包含此屬性非常重要。
我們可以使用以下規則來實現此目的:
img:not([alt]) { border: 2px red dashed; }
See the Pen Attribute Selectors #3 by David Gwyer ( @dgwyer ) on CodePen .0
如果要匹配屬性值的特定部分,則可以使用一些非常有用的選擇器。
-
A[attr^=val]
– 屬性值以val
開頭。 -
A[attr|=val]
– 屬性值以val
開頭,或者以val-
開頭。 -
A[attr$=val]
– 屬性值以val
結尾。 -
A[attr*=val]
– 屬性值中包含val
。 -
A[attr~=val]
– 匹配用空格分隔的屬性值列表,並且列表中包含val
。
以下是每個例子:
See the Pen Attribute Selectors #4 by David Gwyer ( @dgwyer ) on CodePen .0
前兩個示例非常相似,不同之處是 A[attr|=val]
匹配後跟一個 -
字串的值。 這對於匹配語言屬性 lang
很有用。 例如 <p lang ="en-us">
。
使用 A[attr$="val"]
可以輕鬆匹配副檔名,並且與 ::after
相結合你可以輕鬆顯示匹配檔案。 注意使用 attr()
方法和 content
屬性將它與靜態字串連線起來。
A[attr*=val]
顯示了無論使用何種協議或子域,您都可以匹配特定域 mysite.com
。
最後, A[attr~=val]
,它非常適合匹配由空格分隔的值列表組成的屬性中的值。 這隻匹配整個單詞而不是單詞片段,而 *=
匹配單詞片段,因此單詞複數形式將不匹配。這個有點不好理解:例如某 div 元素的 categories
屬性為 <div categories="table wooden maple">
,其 categories
屬性用空格分隔。那麼 div[categories~="table"]
將匹配各元素,還有一個特別要注意的是, <div categories="wooden maple table">
也將被匹配。而 <div categories="wooden maple tables">
或者 <div categories="wooden tableee maple">
都不會被 div[categories~="table"]
匹配。
以上所有屬性選擇器示例都區分大小寫。 但是我們有一個技巧。 如果我們在結束方括號之前插入一個 i
,我們可以啟用區分大小寫的匹配,這有點類似於 JavaScript/">JavaScript 中的正則表示式匹配。
See the Pen Attribute Selectors #5 by David Gwyer ( @dgwyer ) on CodePen .0
除 Internet Explorer 和 Microsoft Edge 外,大多數主流瀏覽器都支援不區分大小寫的匹配。
使用者互動選擇器
如果您處理過表單樣式,那麼您之前無疑會遇到這些型別的偽類選擇器:
- :enabled
- :disabled
- :checked
例如,我們可以使用 :checked
來設定一個簡單的待辦事項列表。
See the Pen User Interface Selectors #1 by David Gwyer ( @dgwyer ) on CodePen .0
這是非常標準的,但我們可以使用其他一些有趣的偽類。 :default
匹配一個或多個元素,這些元素是一組相關元素中的預設元素。這也可以與復位按鈕型別組合使用。
See the Pen User Interface Selectors #2 by David Gwyer ( @dgwyer ) on CodePen .0
我們可以使用偽類選擇器來匹配輸入值是否與 CSS 直接有效,以及在提交表單之前檢查是否需要任何元素。
- :valid
- :invalid
- :required
- :optional (即不必須)
See the Pen User Interface Selectors #3 by David Gwyer ( @dgwyer ) on CodePen .0
如果您開始輸入個人 email 輸入欄位,則必須檢查有效性。 但是,工作 email 地址始終是必需的,並且需要有效檢查有效性,因此不能留空。 還要注意我們可以連結偽類選擇器(例如 :required:invalid
)來實現我們所需要的。
接下來,如果表單元素(支援 min
和 max
屬性)在範圍內,我們有兩個可以匹配的偽類。
- :in-range
- :out-of-range
See the Pen User Interface Selectors #4 by David Gwyer ( @dgwyer ) on CodePen .0
同樣,我們可以使用重置按鈕型別來重置數字輸入元素的預設值。
為了完善本節,我們來看看 :read-only
, :read-write
和 :placeholder-shown
的偽類。
See the Pen User Interface Selectors #5 by David Gwyer ( @dgwyer ) on CodePen .0
使用這些可以輕鬆匹配只讀或可寫(可編輯)的元素。 匹配元素不必是表單輸入欄位,如示例中所示。
最後, :placeholder-shown
將匹配尚未與之互動的元素,並仍顯示預設佔位符文字。 應謹慎使用此特定選擇器,因為它尚未得到廣泛支援。
結構選擇器
結構選擇器非常強大,基於它們在DOM中的位置匹配元素。 它們使您可以靈活地將元素與CSS完全匹配,否則需要 JavaScript 執行相同的操作。
這種型別的選擇器與顯示的選擇器不同,因為其中一些選擇器允許您傳入引數來修改選擇器的工作方式。
例如: nth-child()
接收一個值,該值將匹配特定子元素相對於其父容器的值。
因此,如果我們有一個專案列表,則以下選擇器將匹配第三個專案:
ul:nth-child(3)
但是,引數不是必須是簡單的數字,它可以是一個簡單的表示式,而使偽類更強大。
有效表示式有:
ul:nth-child(2) ul:nth-child(4n) ul:nth-child(2n + 1) ul:nth-child(3n - 1) ul:nth-child(odd) ul:nth-child(even)
表示式變數 n
總是從零開始,因此確切地計算出哪些元素將匹配, n
從 0
開始,然後 n
為 1
,依此類推以編譯元素列表。
這裡還有 1 個簡單而實用的小技巧,我們把 n
當做負數來用,會發生什麼呢?
ul li:nth-child(-n+3) ul li:nth-child(-2n+6) ul li:nth-child(n + 10):nth-child(-n + 12)
例如:
See the Pen jXOeKY by feiwen8772 ( @feiwen8772 ) on CodePen .0
您可以將簡單表示式與以下結構選擇器一起使用:
:nth-child() :nth-last-child() :nth-of-type() :nth-last-of-type()
See the Pen Structural Selectors #1 by David Gwyer ( @dgwyer ) on CodePen .0
:nth-last-child()
和 :nth-last-of-type()
非常類似於 :nth-child()
和 nth-of-type()
,唯一區別是 :nth-last-child()
和 :nth-last-of-type()
是從最後一個元素開始匹配,而不是第一個元素開始匹配。
通過玩各種組合,您可以通過選擇器獲得相當多的創意。 例如,之前的示例包含選擇器:
ul:last-of-type li:nth-last-of-type(2)::after { content: "(2nd from end)"; /* Other styles… */ }
這匹配第 2 個無序列表中最後一個列表項之後的偽元素。 如果你一直在努力解碼一個複雜的選擇器,那麼最好從右到左閱讀它,這樣它就可以在邏輯上解構。
下一組選擇器是專用的結構選擇器,因為它們只匹配特定的子元素。 您無法將表示式傳遞給它們以修改其行為。
:first-child :last-child :only-child :first-of-type :last-of-type
See the Pen Structural Selectors #2 by David Gwyer ( @dgwyer ) on CodePen .0
乍一看,這裡有很多事情,你在使用這些型別的選擇器時需要小心,因為你可能得到你沒想到的結果。
例如,您可能想知道為什麼在 <section>
標記內的等等……文字是藍色的。 實際上所有部分內容都是藍色的,因為它是主 div 容器的最後一個子節點。 其他部分元素通過其他選擇器覆蓋自己的顏色,使單個段落變為藍色。
如果你覺得這些結構選擇器還不夠,或者你覺得記不住,使用起來很麻煩,那麼你可以使用Family.scss – 輕鬆搞定這些 :nth-child
偽類 :nth-child
否定、排除選擇器
CSS 否定偽類選擇器 :not(X)
,是以一個簡單的以選擇器 X
為引數的功能性標記函式,將從匹配的元素集合中排除選擇器 X
所匹配的元素。選擇器 X
中不能包含另外一個 :not
選擇器。
:not()
偽類的優先順序即為它引數選擇器的優先順序。 可以利用這個偽類提高規則的優先順序。例如, #foo:not(#bar)
和 #foo
會匹配相同的元素。 但是前者的優先順序更高。但是 :not()
偽類不像其它偽類,它不會增加選擇器的優先順序。
:not()
偽類可以將一個或多個以逗號分隔的選擇器作為其引數。但是以多個以逗號分隔的選擇器作為引數是實驗性的,尚未廣泛支援。
:not()
偽類時我們得選擇器組合更加靈活,我們來看一些簡單應用:
See the Pen :not() 偽類 by feiwen8772 ( @feiwen8772 ) on CodePen .0
上例中, .content :not(.notice) em
匹配了 .content
中所有的 em
元素,但是排除了 .content .notice
中 em
元素。
我們再來看看 :not()
和其他偽類選擇器結合的例子:
See the Pen :not偽類 by feiwen8772 ( @feiwen8772 ) on CodePen .0
在做一個有間隔線的列表時,我們通常會去除最後一個 li
下的橫線。 li:not(:last-child)
表示除了最後一個 li
元素之外的所有其他 li
元素。
內容選擇器
這些屬於用於匹配內容的一組專用選擇器。我們可以立即使用的是:
-
::first-line
-
::first-letter
-
::selection
– 相容方案: https://www.css88.com/archives/5169
See the Pen Content Selectors #1 by feiwen8772 ( @feiwen8772 ) on CodePen .0
::first-line
和 ::first-letter
僅在應用於塊級元素時才起作用。另外要小心只在特定元素上使用 ::first-letter
,否則每個段落都可能會應用。
目前還沒有一些令人興奮的內容選擇器,但是當它們得到支援時,它們將開啟各種可能性。
以下是需要注意的內容選擇器列表:
-
::inactive-selection
— 非活動視窗內的選定內容 -
::spelling-error
— 檢查可編輯元素的拼寫和語法 -
::grammar-error
— 匹配語法錯誤 -
::marker
— 匹配列表項標記 -
::placeholder
— 匹配表單元素的 placeholder 文字樣式;相容方案: https://www.css88.com/archives/5689
其他選擇器
我們接下來提到其他幾個選擇器不適合不適合歸類到上面任何類別。 別擔心我們差不多完成了! 不幸的是,其中大部分是實驗性的,所以你必須等待一段時間才能在生產中使用它們。
:target
選擇器的目標是一個 id
與當前 URL
的一部分匹配的元素。 比如下面 URL
匹配該URL頁面中 id
為 part1
的元素:
https://css88.com#part1
我們可以將該元素應用以下樣式:
:target { border: 1px red solid; }
其實 :target
選擇器目前可以用於一些特殊的用例,歡迎檢視::target 偽類使用技巧
如果你有一個很大的選擇器,那麼 :matches()
可以幫助簡化它。例如,如果您有以下選擇器:
nav p.content, header p.content, main p.content, sidebar p.content, footer p.content { margin: 15px; padding: 10px; }
然後可以通過 :matches()
簡化,相當於:
太好了!這將有助於使樣式表更具可讀性。
接下來我們還有一個 :any-link
選擇器,這個選擇器是 :link
和 :visited
組合的簡寫。 所以下面這兩個選擇器實際上是相同的:
:any-link { color: red; } :link, :visited { color: red; }
本文中最後兩個選擇器:
:dir() :lang()
這些都與您網站的語言有關。
:dir()
接受引數 ltr
或 rtl
,具體取決於您要匹配的文字的方向,目前僅 Firefox 支援。
所以: :dir(rtl)
會匹配所有具有 RTL 方向內容的元素。
HTML文件中的每個元素都可以使用 lang
屬性設定自己的單獨語言。
<div lang="en">The language of this element is set to English.</div> <div lang="el">Η γλώσσα αυτού του στοιχείου έχει οριστεί στα ελληνικά.</div> <div lang="is">Tungumál þessa þáttar er sett á íslensku.</div>
將相同的基本文字輸入到三個 <div>
標記中,但將特定國家/地區新增到內容的末尾。此外, lang
屬性中使用的國家程式碼代表相應的國家/地區。
:lang(en) { color: red; } :lang(el) { color: green; } :lang(is) { color: blue; }
演示:
See the Pen Misc Selectors by David Gwyer ( @dgwyer ) on CodePen .0
好訊息是所有主流瀏覽器都支援 :lang()
選擇器。
資源
如果你試圖查詢一個選擇器,或者需要深入研究CSS規範,那麼你可能需要檢視一些有用的資源:
最後…
我希望你會發現這篇文章很有用。 可以幫助重新整理你的CSS選擇器技能,並嘗試各種可能性。
使用純 CSS 可以做很多很酷的事情,這在幾年前是不可能實現的。
對於能夠在純 CSS 中進行一些非常高階的樣式和動畫的設計師來說,這是令人興奮的,並且所有人都看不到一行 JavaScript 。
本文大部分內容來自: https://blog.logrocket.com/level-up-your-css-selector-skills-5d7bb45ddd37 ,在這篇文章的基礎上做了很多內容的改進。
如果你覺得本文對你有幫助,那就請分享給更多的朋友
關注「前端乾貨精選」加星星,每天都能獲取前端乾貨
