谁动了我的选择器?深入理解CSS选择器优先级
深入理解CSS選擇器優先級
- 😏序言
- 🧐文章內容搶先看
- 🤐一、基礎知識
- 1、為什么CSS選擇器很強
- 2、CSS選擇器的一些基本概念
- (1)4種基本概念
- Ⅰ. 選擇器
- Ⅱ. 選擇符
- Ⅲ. 偽類
- Ⅳ. 偽元素
- (2)CSS選擇器的命名空間
- 😲二、CSS選擇器的優先級
- 1、優先級規則概覽
- (1)選擇器優先級
- (2)選擇器說明
- 2、優先級計算
- (1)選擇器優先級計算
- (2)“后來居上”原則
- (3)提升優先級的小技巧
- 🥳三、結束語
- 🐣彩蛋 One More Thing
- 🏷?往期推薦&參考資料
- 🏷?番外篇
😏序言
在前端的面試中,有一道很普遍的題目,就是CSS選擇器的優先級。原來周一覺得這個東西好像蠻簡單的,就是認知里面的類選擇器、id選擇器和標簽,然后就沒了。但是殊不知很多時候我們都輸給了“我以為”,事實證明一切內容并沒有想象中的那么簡單。
當我看完書的時候,才發現優先級需要通過計算來確定,然后呢,還有通配選擇器、選擇符和邏輯組合偽類等等各種類型的計算。
在沒有看書之前,我對這些內容的想法可能是這樣的:
因此,寫下這篇文章,總結關于 CSS 選擇器中的優先級。一起來學習⑧~💡
🧐文章內容搶先看
在開始講解本文之前,我們先用一張思維導圖來了解本文的結構內容。詳情見下圖👇
接下來開始進入本文的講解~
🤐一、基礎知識
1、為什么CSS選擇器很強
- 傳統編程語言講求邏輯清晰,層次分明,并且主要為功能服務。
- 但 CSS 卻是為樣式服務的,它重表現,輕邏輯,如同人的思想一樣,相互碰撞才能產生火花。
- 對于 CSS 選擇器來說,它作為 CSS 世界的支柱,其作用好比人類的脊柱,與 HTML 結構、瀏覽器行為、用戶行為以及整個 CSS 世界相互依存、相互作用,這必然會產生很多碰撞,使得 CSS 選擇器變得非常強悍。
2、CSS選擇器的一些基本概念
(1)4種基本概念
CSS選擇器可以分為4類,即選擇器、選擇符、偽類和偽元素。下面介紹這四種類型的區別。
Ⅰ. 選擇器
選擇器,指的是我們平常使用的 css 聲明塊前面的標簽、類名等等。比如:
body{background: #333; }以上代碼中的 body 就是一種選擇器,是類型選擇器,也可以稱為標簽選擇器。
再比如:
.container{background-color: #fff; }以上代碼中的 .container 也是選擇器,屬于屬性選擇器中的一種,我們也經常稱它為類選擇器。
Ⅱ. 選擇符
CSS 中有5種選擇符,分別為:
| 空格( ) | 表示后代關系 |
| 尖括號(>) | 表示父子關系 |
| 加號(+) | 表示相鄰兄弟關系 |
| 波浪號(~) | 表示兄弟關系 |
| 雙管道(||) | 表示列關系 |
我們來舉些例子,更好的理解這幾種選擇符。具體代碼如下:
/* 后代關系 */ .container img {object-fit: contain; }/* 父子關系 */ ol > li {margin: 0 auto; }/* 相鄰兄弟關系 */ button + p {margin-right: 10px; }/* 兄弟關系 */ button ~ p {margin-left: 10px; }/* 列 */ .col || td {background-color: gray; }這里需要注意的是,相鄰兄弟關系和兄弟關系的區別,這兩個看起來很相似,很容易混淆。
對于 + 的相鄰關系,指的是當前的 button 以及在它同一層級上的下一個元素 p 的樣式;而對于 ~ 來說,就是當前 button 以及在它同一層級上的所有 p 元素的樣式。
可以說 + 號是一對一關系,而 ~ 則是一對多關系。
Ⅲ. 偽類
偽類的特征是其前面會有一個冒號 : 。對于偽類來說,它通常與瀏覽器行為和用戶行為相關聯,可以把它看成是 css 世界中的 javascript 。比如:
a:hover{color: gray; }Ⅳ. 偽元素
偽元素的特征是其前面會有兩個冒號 :: ,常見的有 ::before 、 ::after 、 ::first-letter 和 ::first-line 等。
(2)CSS選擇器的命名空間
CSS 選擇器中還有一個命名空間的概念。所謂命名空間,就是我們平常所看到的 @namespace ,主要作用是用來避免沖突。
比如說,我們在 html 和 svg 中都會用到 <a> 鏈接,這個時候就很可能會發生沖突。那問題來了,沖突制造了,又該怎么解決呢?這個時候就可以用剛剛提到的命名空間 @namespace 來解決。
我們來看一段代碼,更直觀的了解命名空間。具體代碼如下:
<p>這是文字:<a>點擊刷新</a> </p> <p>這是SVG:<svg><a xlink:href><path d="M433.109 23.694c...2.706z"/></a></svg> </p> @namespace url(http://w3.org/1999/xhtml); @namespace svg url(http://www.w3.org/2000/svg); /* 管道符 */ svg|a {color: black;fill: currentColor; } /* 標簽選擇器 */ a {color: gray; }大家可以看到, svg|a 中有一個管道符 | ,那么管道符前面的字符表示的就是命名空間的代稱,而管道符后面的內容則是選擇器。這段代碼最終的顯示效果是這樣的:
如果按照我們預定的,可能有的小伙伴覺得樣式不是越靠后優先級越高嗎,而為什么 svg 中的 a 還是顯示了黑色,而不是灰色呢?
其實,大家可以看到上面的命名空間,上述代碼中就表示了,在 http://www.w3.org/2000/svg 這個命名空間下所有 <a> 的顏色都是黑色 black ,且由于 xhtml 的命名空間(大家定位到第一個命名空間)也被指定了。因此呢, svg 中的 <a> 標簽也就不會受到 標簽選擇器a 的影響,即便 純標簽選擇器a 的優先級再高,那也是無效的。
講到這個,我們來對 css選擇器命名空間 做個小結:
其實, css選擇器命名空間 的兼容性很好,至少相似10年前瀏覽器就支持了。但是呢,確很少有人在項目中去使用它。這是為什么呢?
原因主要有以下兩點:
-
在 html 中直接內聯 svg 的應用場景相對來說還是比較少的,你可以試想一下,我們平常在引用阿里圖標的時候,會直接把svg那一大串資源,給自己引入到自己的頁面中嗎?應該沒有人這么干吧。所以,它更多的是作為獨立資源來使用。
-
還有一個原因就是,有它更好的替代方案。比如:
svg a{color: black; }這樣做的唯一缺點就是,增加了 svg 中 a 元素的優先級。但是再大多數的情況下,對我們的開發基本上沒什么影響。
所以呢,對于 css 選擇器的命名空間,大家可以選擇了解即可,至少在遇到大規模沖突場景下,給自己多一個解決方法~
😲二、CSS選擇器的優先級
幾乎所有的 css 樣式沖突、樣式覆蓋等等問題,都跟 css 聲明的優先級錯位脫不開關系。接下來,我們將從 css 優先級規則以及優先級的計算為切入點,來了解關于 css 選擇器的優先級。
1、優先級規則概覽
(1)選擇器優先級
css 優先級有著明顯的不可逾越的等級制度,因此,我們可以將其劃分為 0~5 這 6 個等級。其中,前4個等級由 css選擇器 決定,后2個等級由 書寫形式 和 特定語法 決定。 下面來了解這6種等級制度各自的區別,具體如下表:
| 0級 | 通配選擇器、選擇符和邏輯組合偽類 | 0 |
| 1級 | 標簽選擇器 | 1 |
| 2級 | 類選擇器、屬性選擇器和偽類 | 10 |
| 3級 | ID選擇器 | 100 |
| 4級 | style屬性內聯 | 1000 |
| 5級 | !important | 10000 |
(2)選擇器說明
繼續,我們對這6個級別對應的選擇器樣式來做個簡單的了解。具體如下:
0級:通配選擇器、選擇符和邏輯組合偽類
/* 通配選擇器指星號(*) */ * {color: #fff; }/* ------------------分割線------------------- *//* 選擇符指+、>、~、空格和|| 具體上面有做詳細說明,不再細述 */ .container img {/* 后代關系 */ }ol > li {/* 父子關系 */ }button + p {/* 相鄰兄弟關系 */ }button ~ p {/* 兄弟關系 */ }.col || td {/* 列 */ }/* ------------------分割線------------------- *//* 邏輯組合偽類有:not()、:is()和:where()需要注意的是,只有邏輯組合偽類的優先級是0,其他偽類的優先級并不是這樣的 */ :not() {color: #fff; }1級:標簽選擇器
/* 標簽選擇器類似于body,p,span,div等等這些標簽元素 */ body {color: #333; }2級:類選擇器、屬性選擇器和偽類
/* 類選擇器指class */ .container {color: #666; }/* ------------------分割線------------------- *//* 屬性選擇器指指針對某個標簽里面的屬性進行特定標識比如以下,表示只對有 href 屬性的錨(a 元素)應用樣式 */ a[href] {color:#666; }/* ------------------分割線------------------- *//* 偽類指:hover等 */ a:hover {color: #666; }3級:ID選擇器
#container {color: #999; }4級:style屬性內聯
<span style="color: #ccc;">優先級 </span>5級:! important
/* !important是頂級優先級,可以重置 js 設置的樣式,唯一推薦使用的場景就是使 js 設置無效(切勿濫用)*/ #container {color: #999 !important; }2、優先級計算
上面我們了解到了關于 css 選擇器的各種玩法,那下面我們就來看一下它是怎么玩的。
(1)選擇器優先級計算
我們用一個表格來羅列處常見的一些計算。當然,大家也可以拿起小本本邊看邊進行計算。具體如下表:
| *{ } | 0 | 1個0級通配選擇器,優先級數值計算結果為0 |
| p { } | 1 | 1個1級通配選擇器,計算結果為1 |
| ul > li { } | 2 | 2個1級標簽選擇器,1個0級選擇符,計算結果為1+0+1 |
| li > ol + ol { } | 3 | 3個1級標簽選擇器,2個0級選擇符,計算結果為1+0+1+0+1 |
| .foo { } | 10 | 1個2級類名選擇器,計算結果為10 |
| a:not([rel=nofollow]) { } | 11 | 1個標簽選擇器,1個0級否定偽類,1個2級屬性選擇器,計算結果為1+0+10 |
| a:hover { } | 11 | 1個1級標簽選擇器,1個2級偽類,計算結果為1+10 |
| ol li.foo { } | 12 | 2個1級標簽選擇器,1個2級類名選擇器,1個0級空格選擇符,計算結果為1+0+1+10 |
| li.foo.bar { } | 21 | 1個1級標簽選擇器,2個2級類名選擇器,計算結果為1+10+10 |
| #foo { } | 100 | 1個3級id選擇器,計算結果為100 |
| #foo .bar p { } | 111 | 1個3級id選擇器,1個2級類名選擇器,1個1級標簽選擇器,2個0級空格選擇器,計算結果為100+10+1+0+0 |
(2)“后來居上”原則
還有一種可能會出現的情況就是,遇到計算結果相同的,我們該如何取值呢?比如:
<html lang=“zh-CN”><body class="foo">顏色是</body> </html><style>body.foo:not([dir]) {color: red;}html[lang] > .foo {color: blue;} </style>我們來分析下以上這段代碼。首先,第一段 css 代碼中,出現1個標簽選擇器 body ,1個類名選擇器 .foo 和1個否定偽類 :not ,以及1個屬性選擇器 [dir] 。因此計算結果為 1+10+0+10 ,也就是 21 。
我們再來分析第二段代碼, html[lang] > .foo 中出現1個標簽選擇器 html ,1個屬性選擇器 [lang] ,1個類名選擇器 .foo ,這里 0級選擇器 忽略不計。因此,最終計算結果為 1+10+10=21 。
所以,大家可以看到,兩個最終的計算結果都是 21 。那我們到底用哪個樣式呢?
印證標題所說的,遵循**“后來居上”原則**, 最終這段代碼顯示為藍色。
(3)提升優先級的小技巧
在實際開發中,我們難免會遇到需要增加 css 選擇器優先級的場景。殊不知很多小伙伴可能直接就把內聯和 !important 直接懟上去了,這樣子造成的后果可能有點恐怖了。
所以,我們需要來了解幾種增加選擇器權重的做法。具體如下:
假設現在我要給下面這段代碼增加權重,例如:
.foo {color: #333; }很多時候我們的做法可能是增加嵌套或者是增加一個標簽選擇器,例如:
/* 增加嵌套 */ .father .foo {}/* 增加標簽選擇器 */ div.foo {}但是這種做法往往不是最好的,因為它會增加了代碼的耦合度,降低代碼的可維護性。試想一下,一旦類名變了,或者標簽換了,那你的樣式豈不是就要往回去改了,這樣會不會就有點不太友好了。
所以,我們引出一下兩種方式,來解決這個問題。具體如下:
第一種: 重復選擇器自身
.foo.foo {}第二種: 借助已存在的屬性選擇器
.foo[class] {}#foo[id] {}這樣看起來,會不會就友好了許多呢。
🥳三、結束語
在上文中,我們講到關于 css 選擇器的一些基礎知識,以及 css 選擇器的優先級的各種計算方式,還有關于“后來居上”原則和一些提升優先級的小tips。
講到這里,關于 css 選擇器優先級的講解就結束啦!希望對大家有幫助~
🐣彩蛋 One More Thing
🏷?往期推薦&參考資料
position和z-index👉你可能對position和z-index有一些誤解
書籍👉張鑫旭老師的《CSS選擇器世界》
🏷?番外篇
- 關注公眾號星期一研究室,第一時間關注優質文章,更多精選專欄待你解鎖~
- 如果這篇文章對你有用,記得留個腳印jio再走哦~
- 以上就是本文的全部內容!我們下期見!👋👋👋
總結
以上是生活随笔為你收集整理的谁动了我的选择器?深入理解CSS选择器优先级的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 划船机减肥效果如何
- 下一篇: 2024年度北京普惠健康保服务增至49项