CSS 屬性選擇器,可以通過已經存在的屬性名或屬性值比對元素。
屬性選擇器是在 CSS2 中引入的并且在 CSS3 中得到了很好拓展。本文将會比較全面的介紹屬性選擇器,盡可能的去挖掘這個選擇器在不同場景下的不同用法。
[attr]:該選擇器選擇包含 attr 屬性的所有元素,不論 attr 的值為何。
[attr=val]:該選擇器僅選擇 attr 屬性被指派為 val 的所有元素。
[attr~=val]:該選擇器僅選擇具有 attr 屬性的元素,而且要求 val 值是 attr 值包含的被空格分隔的取值清單裡中的一個。
下面幾個屬于 CSS3 新增文法,也被稱為“僞正則選擇器”,因為它們提供類似 regular expression 的靈活比對方式。
[attr|=val] : 選擇attr屬性的值是 val 或值以 val- 開頭的元素(注意,這裡的 “-” 不是一個錯誤,這是用來處理語言編碼的)。
[attr^=val] : 選擇attr屬性的值以 val 開頭(包括 val)的元素。
[attr$=val] : 選擇attr屬性的值以 val 結尾(包括 val)的元素。
[attr*=val] : 選擇attr屬性的值中包含子字元串 val 的元素(一個子字元串就是一個字元串的一部分而已,例如,”cat“ 是 字元串 ”caterpillar“ 的子字元串
屬性選擇器最基本的用法,就是通過元素的屬性值去選擇 DOM 元素。像這樣,将選中所有帶 <code>href</code> 屬性的DOM 元素:
CodePen Demo -- 屬性選擇器基本用法
選擇一個 img 标簽,它含有 title 屬性,并且包含類名為 logo 的元素。
<code>i</code> 參數
忽略類名的大小寫限制,選擇包含 class 類名包含子字元串為 text,Text,TeXt... 等情況的 p 元素。 這裡的 i 的含義就是正則裡面參數 i 的含義,ignore,忽略大小寫的意思。
是以上面的選擇器可以選中類似這樣的目标元素:
<code>g</code> 參數
與正規表達式不一樣,參數 <code>g</code> 在這裡表示大小寫敏感(case-sensitively)。然而,這個屬性目前仍未納入标準,支援的浏覽器不多。
CodePen Demo -- 屬性選擇器的僞正則用法
還有一種比較常用的場景就是搭配<code>:not()</code> 僞類,完成一些判斷檢測性的功能。譬如下面這個選擇器,就可以選取所有沒有 <code>[href]</code> 屬性的 <code>a</code> 标簽,添加一個紅色邊框。
當然,複雜一點,我們可以搭配不僅僅一個 <code>:not()</code>僞類,像是這樣,可以同時多個配合使用,選擇一個 href, target, rel 屬性都沒有的 a 标簽:
CodePen Demo -- 屬性選擇器配合 :not 僞類
甚至乎,如果有這種場景,我們還可以覆寫掉行内樣式,像這樣:
我們可以使用屬性選擇器強制覆寫掉上述樣式:
當然,屬性選擇器不一定隻是單單的進行标簽的選擇。
配合上僞元素,我們可以實作很多有助提升使用者體驗的功能。
這裡有一個小知識點,僞元素的 <code>content</code> 屬性,通過 <code>attr(xxx)</code>,可以讀取到對應 DOM 元素标簽名為 xxx 的屬性的值。
是以,配合屬性選擇器,我們可以很容易的實作一些角标功能:
這裡右上角的數字 5 提示角标,就是使用屬性選擇器配合僞元素實作,可以适應各種長度,以及中英文,能夠節省一些标簽。CodePen Demo -- 屬性選擇器實作角标功能
我們都知道,如果給一個圖檔添加一個 title 屬性,當 hover 到圖檔上面的時,會展示 title 屬性裡面附加的内容,類似這樣:
這裡不一定是 <code>img</code> 标簽,其他标簽添加 <code>title</code> 屬性都能有類似的效果。但是這裡會有兩個問題:
響應太慢,通常滑鼠 hover 上去要隔 1s 左右才會出現這個 title 框
框體結構無法自定義,彈出框的樣式無法自定義
是以這裡,如果我們希望有一些自己能夠控制樣式的可快速響應的浮層,可以自定義一個類 title 屬性,我們把它稱作 <code>popTitle</code>,那麼可以這樣操作:
對比一下,第一個是原生自帶的 <code>title</code> 屬性,下面兩個是使用屬性選擇器配合僞元素模拟的提示:
浏覽器自帶的 <code>title</code> 屬性延遲響應是添加一層防抖保護,避免頻繁觸發,這裡也可以通過對僞元素添加一個100毫秒級的 <code>transition-delay</code> 實作延遲展示。
CodePen Demo -- 屬性選擇器配合僞元素實作類 title 功能
好,上面的運用執行個體我們再拓展一下,考慮如何更好的運用到實際業務中,其實也是有很多用武之地的。譬如說,通過屬性選擇器給圖檔添加标簽,類似一些電商網站會用到的一個效果。
我們希望給圖檔添加一些标簽,在 hover 圖檔的時候展示出來。
當然,CSS 中,諸如 <code><img></code> 、<code><input></code>、<code><iframe></code>,這幾個标簽是不支援僞元素的。
是以這裡我們輸出 DOM 的時候,給 img 的父元素帶上部分圖檔描述标簽。通過 CSS 去控制這些标簽的展示:
看看效果:
CodePen Demo -- 通過屬性選擇器給圖檔添加标簽
我們知道,HTML5 對标簽新增了一個 download 屬性,此屬性訓示浏覽器下載下傳 URL 而不是導航到它。
那麼,我們可以利用屬性選擇器對所有帶此類标簽的元素進行提示。像這樣:
當我們 hover 到這個連結的時候,就會這樣,提示使用者,這是一個可以下載下傳的按鈕:
CodePen Demo -- 屬性選擇器配合僞元素做下載下傳提示
現在大部分網站不是切了 https 就是走在切 https 的路上。如果頁面上的連結很多或者對跳轉頁面的協定有要求,使用屬性選擇器配合僞元素對連結的協定進行提示也不失為一種好方法。
CodePen Demo -- 屬性選擇器配合僞元素對連結的協定進行提示(http/https)
當然,僞元素的内容不一定是純文字的,為了給使用者更好的體驗,圖或者圖檔加文字也是可以的。
譬如我們可以形象化地給 https 連結站點再加一個小綠鎖,符合使用者的一些正常認知。
這裡我将小綠鎖的圖檔使用 base64 嵌入到僞元素當中,簡單的使用 <code>text-indent</code> 控制圖文的排布:

這裡隻是一個非常小的 Demo,實際情況是大部分使用者并不了解這個小綠鎖的含義,是以實際使用應該搭配文字輔助提示。
CodePen Demo -- 屬性選擇器配合僞元素對https協定進行圖文提示
也可以對一些可下載下傳資源進行視覺上 icon 的提示。
CodePen Demo -- 屬性選擇器選擇檔案名字尾
屬性選擇器其實對 <code>input</code> 類型的元素是一個很好的幫手,因為 <code>input</code> 常用,且經常搭配很多不同功能的屬性值。
隻不過,由于 <code>input</code> 類型無法添加僞元素。是以搭配屬性選擇器更多的通過屬性的各種狀态改變自身的樣式。
簡單舉個例子,譬如:
這裡,我們選擇了 <code>type=text</code> 并且擁有 <code>disabled</code> 屬性的 <code>input</code> 元素,将它的背景色和邊框色設定為灰色。給與使用者更好的視覺提示。
考慮這個問題,下面兩個選擇器是否等值?
上述兩個選擇器,作用完全一緻。然而,如果是下面這種情況,兩者就不一樣了:
這裡,ID 選擇器<code>#header</code>比屬性選擇器<code>[id="header"]</code>的權重更高,雖然兩者能夠選擇同樣的元素,但是兩者并不完全等價。
考慮下面三種情況,是否一緻?
事實上,從 HTML2 開始,不添加引号的寫法就已經得到支援,是以上述三種寫法都是正确的。
然而,能夠不使用引号也是有限制的,再看看下面這種寫法:
第二個選擇器是個無效選擇器,<code>://</code> 不括起來的話會識别錯誤,必須使用引号引起來像這樣<code>a[href^="http://"]</code>,這裡具體的原因可以看看這篇文章:Unquoted attribute value validator。
是以保險起見,建議都加上引号。
編寫”具有語義的HTML”原則是現代、專業前端開發的一個基礎。當然,我們經常談論到的都是 HTML 語義化。
那麼,CSS 需要語義化嗎?CSS 有語義化嗎?例如上述的例子,使用特定的類名或者 id 選擇器皆可完成。那麼使用屬性選擇器的理由是什麼?
我的了解是,屬性(attribute)本身已經具有一定的語義,表達了元素的某些特征或者功能,利用屬性選取元素再進行對該屬性值的特定操作,一定程度上也可以輔助提升代碼的語義化。至少的提升了 CSS 代碼的可讀性。但是 CSS 是否需要語義化這個問題就見仁見智了。
這裡有幾篇文章還涵蓋了很多其他方面使用,可以對比觀看:
Semantic CSS With Intelligent Selectors
Splicing HTML’s DNA With CSS Attribute Selector
更多精彩 CSS 技術文章彙總在我的 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。
好了,本文到此結束,希望對你有幫助 :)
如果還有什麼疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。