計算選擇器的特異性
每個 CSS Selector 都有自己的特定值。序列中的每個選擇器都會增加序列的整體特異性。選擇者屬於三個不同的特異性組之一: A , B 和 c 。當多個選擇器序列選擇給定元素時,瀏覽器使用具有最高整體特異性的序列應用的樣式。
A 組是最具體的,其次是 B 組,最後是 C 組。
通用選擇器(*
)和組合器(如 >
和~
)沒有特異性。
示例 1:各種選擇器序列的特異性
#foo #baz {} /* a=2, b=0, c=0 */
#foo.bar {} /* a=1, b=1, c=0 */
#foo {} /* a=1, b=0, c=0 */
.bar:hover {} /* a=0, b=2, c=0 */
div.bar {} /* a=0, b=1, c=1 */
:hover {} /* a=0, b=1, c=0 */
[title] {} /* a=0, b=1, c=0 */
.bar {} /* a=0, b=1, c=0 */
div ul + li {} /* a=0, b=0, c=3 */
p::after {} /* a=0, b=0, c=2 */
*::before {} /* a=0, b=0, c=1 */
::before {} /* a=0, b=0, c=1 */
div {} /* a=0, b=0, c=1 */
* {} /* a=0, b=0, c=0 */
示例 2:瀏覽器如何使用特異性
想象一下以下的 CSS 實現:
#foo {
color: blue;
}
.bar {
color: red;
background: black;
}
這裡我們有一個 ID 選擇器,它將 color
宣告為藍色,一個類選擇器將 color
宣告為紅色,將 background
宣告為黑色。
兩個宣告將選擇 ID 為 #foo
和 .bar
類的元素。ID 選擇器具有 A 組特異性,類選擇器具有 B 組特異性。ID 選擇器超過任意數量的類選擇器。因此,來自 #foo
選擇器的 color:blue;
和來自 .bar
選擇器的 background:black;
將應用於該元素。ID 選擇器的更高特異性將導致瀏覽器忽略 .bar
選擇器的 color
宣告。
現在想象一下不同的 CSS 實現:
.bar {
color: red;
background: black;
}
.baz {
background: white;
}
這裡我們有兩個類選擇器; 其中一個宣稱 color
為紅色,background
為黑色,另一個宣稱 background
為白色。
具有 .bar
和 .baz
類的元素將受到這兩個宣告的影響,但是我們現在遇到的問題是 .bar
和 .baz
具有相同的 B 組特異性。CSS 的級聯性質為我們解決了這個問題:由於 .baz
是在 .bar
之後定義的,我們的元素最終得到了來自 .bar
的紅色 color
,但是來自 .baz
的白色 background
。
例 3:如何操作特異性
可以操作上面示例 2 中的最後一個片段,以確保使用 .bar
類選擇器的 color
宣告而不是 .baz
類選擇器的宣告。
.bar {} /* a=0, b=1, c=0 */
.baz {} /* a=0, b=1, c=0 */
實現這一目標的最常見方法是找出可以應用於 .bar
選擇器序列的其他選擇器。例如,如果 .bar
類僅應用於 span
元素,我們可以將 .bar
選擇器修改為 span.bar
。這將給它一個新的 C 組特異性,它將覆蓋 .baz
選擇器的缺乏:
span.bar {} /* a=0, b=1, c=1 */
.baz {} /* a=0, b=1, c=0 */
然而,可能並不總是能夠找到在使用 .bar
類的任何元素之間共享的另一個公共選擇器。因此,CSS 允許我們複製選擇器以增加特異性。我們可以使用 .bar.bar
代替 .bar
(參見選擇器的語法,W3C 推薦標準 )。這仍然選擇具有 .bar
類的任何元素,但現在具有組 B 特異性的兩倍 :
.bar.bar {} /* a=0, b=2, c=0 */
.baz {} /* a=0, b=1, c=0 */
!important
和內聯樣式宣告
樣式宣告中的 !important
標誌和 HTML style
屬性宣告的樣式被認為具有比任何選擇器更高的特異性。如果存在這些,它們影響的樣式宣告將否決其他宣告,無論它們的特殊性如何。也就是說,除非你有多個宣告包含適用於同一元素的同一屬性的 !important
標誌。然後,正常的特異性規則將適用於那些相互引用的屬性。
因為它們完全覆蓋了特異性,所以在大多數使用案例中都不贊成使用 !important
。人們應該儘可能少地使用它。為了長期保持 CSS 程式碼的有效性和可維護性,增加周圍選擇器的特異性幾乎總是比使用 !important
更好。
!important
並不令人討厭的罕見例外之一是在實現通用助手類時,如 .hidden
或 .background-yellow
類,它們應始終在任何遇到的地方覆蓋一個或多個屬性。即便如此,你還需要知道自己在做什麼。在編寫可維護的 CSS 時,你想要的最後一件事就是在整個 CSS 中使用 !important
標誌。
最後一點
關於 CSS 特異性的一個常見誤解是 A , B 和 C 組值應相互組合(a=1, b=5, c=1
=> 151)。這是不是這種情況。如果是這種情況,擁有 20 個 B 組或 C 組選擇器就足以分別覆蓋單個 A 組或 B 組選擇器。這三組應被視為具體的個體水平。特異性不能用單個值表示。
建立 CSS 樣式表時,應儘可能保持最低的特異性。如果你需要將特異性提高一點來覆蓋另一種方法,那就讓它更高但儘可能低,以使其更高。你不應該有這樣的選擇器:
body.page header.container nav div#main-nav li a {}
這使得未來的變化更加困難並汙染了 css 頁面。
你可以計算出你選擇的特殊性這裡