于 CSSer 來說,多多少少都會遇到過 “樣式規則不生效?”、“樣式規則被覆蓋?” 等等問題,這些都與 CSS 權重有關系。
我自己是一名從事了多年開發的web前端老程序員,目前辭職在做自己的web前端私人定制課程,今年年初我花了一個月整理了一份最適合2019年學習的web前端學習干貨,各種框架都有整理,送給每一位前端小伙伴,想要獲取的可以關注我的頭條號并在后臺私信我:前端,即可免費獲取
選擇器匹配原理
在此之前,容我先簡單介紹瀏覽器是怎么通過各種選擇器,把樣式規則和 DOM 元素扯上關系的。
瀏覽器中存在著專門的渲染引擎來渲染 HTML 文檔。這里以 Webkit 內核為例,在啟動渲染流程時,引擎一方面會解析 HTML 文檔,構建 DOM 節點樹(DOM Tree),另一方面會解析樣式文件生成 樣式規則(Style Rules),然后結合分析 DOM 樹和樣式規則生成 渲染樹(Render Tree),最后 布局 和 繪制 出 UI 界面。
Webkit 渲染流程(摘自 https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/)
CSS 的選擇器匹配就發生在 渲染樹 的構建過程。瀏覽器會從 DOM 樹的根節點開始遍歷每個可見節點,對于每個可見節點都會在規則表中查找適配的樣式規則。那么,如此龐大的樣式數據和復雜的選擇器結構,渲染引擎是怎么尋找到適配當前元素的樣式規則呢?
請看下面這個復合選擇器。如果引擎是按照從左向右的順序匹配選擇器,將會導致大量 回溯 的發生:先是在當前節點到 DOM 樹跟節點的路徑上尋找 div 元素,然后沿著分支路徑繼續往下找第二個 div 元素,如果當前路徑找不到,就得回退到上一個 div 元素嘗試另一條分支路徑。如此往復,對性能損耗將會非常嚴重。
div div span .text {}
所以,引擎是采取 從右向左 的順序來匹配選擇器。也就是 從最具體的選擇器開始,如果與當前節點不匹配,則直接拋棄該條規則;如果匹配,只需要沿著路徑往上確認其他選擇器是否也匹配,這樣做可以大大減少無效的匹配數,提高性能。除此之外,引擎還會把不同類型的選擇器(id、class、tag 及其他類型)歸類到哈希表中,進一步減少查找基數。
了解選擇器的匹配原理,有利于我們理解其權重規則,對于編寫簡潔、高效的 CSS 代碼非常有幫助。
CSS 權重
通過不同的方式(內聯樣式、外部樣式表)、不同類型的選擇器組合針對某個元素聲明樣式規則時,如何決定最終哪個聲明會被應用到元素上?這就涉及到 CSS 權重(也指優先級,Specificity)。
圍繞 CSS 權重主要有以下三條規則:
<html> <head> <style> body div { color: red; } html div { color: blue; } </style> </head> <body> <div>測試</div> </body> <html>
<html> <head> <style> #parent { color: red; } span { color: blue; } </style> </head> <body> <div id="parent"> <span>測試</span> </div> </body> <html>
CSS 權重等級
如何比較不同選擇器的權重高低?這里劃分成 5 個權重等級,按照等級 由高到低 的順序:
<div style="color: #fff;">測試</div>
id 選擇器
#demo {}
類選擇器、屬性選擇器、偽類選擇器
.demo {} [type="text"] {} div:hover {} div:first-child {}
需要注意,否定偽類(:not())比較特殊,它不會對權重產生影響,但是 否定偽類內部的選擇器會影響權重。
<html> <head> <style> div#demo span { color: red; } div:not(#demo) span { color: blue; } </style> </head> <body> <div id="demo"> <span>普通 demo</span> <div id="pseudo"> <span>否定偽類 demo</span> </div> </div> </body> <html>
div {} div:before {} div:after {}
除了上述的選擇器之外,通配符選擇器(*) 和 結合符(+、>、~)對優先級沒有影響。
對于復雜的復合選擇器,我們需要逐個等級比較權重大小,不允許跨越等級比較。為了方便計算,我們可以把權重值具象化,每出現一個選擇器就在其對應的等級區間中權重值加 1,參考下面實例:
* {} /* 權重值 0-0-0-0-0 */ div {} /* 權重值 0-0-0-0-1 */ div h1+h2 {} /* 權重值 0-0-0-0-3 */ div, ... div {} /* 權重值 0-0-0-0-n */ #demo a:hover {} /* 權重值 0-0-1-1-1 */
國外大神 把 CSS 權重的計算模擬成海洋生物鏈,選擇器組合權重越大則在生物鏈位置越高,非常淺顯生動,建議收藏。
圖片轉自 https://specifishity.com/
建議
在充分了解 CSS 選擇器匹配原理和權重規則之后,在編寫 CSS 代碼時不妨多注意以下細節:
<html> <head> <style> div { color: red !important; } /* 通過 id選擇器 增加權重 */ #demo { color: blue !important; } </style> </head> <body> <div id="demo">測試</div> </body> <html>
減少不必要的選擇器嵌套,嵌套最好不要超過三級。大量的復合選擇器,會影響選擇器匹配的效率,同時也會增加 CSS 樣式文件的體積,不易維護。
當出現大量嵌套時,我們可以指定一個更具體的類選擇器來替換復合選擇器。
lt;img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110853564.jpg" data-caption="" data-size="normal" data-rawwidth="711" data-rawheight="230" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110855421.jpg" class="origin_image zh-lightbox-thumb" width="711" data-original="https://pic2.zhimg.com/v2-1a61d5196d8d77ff8fa263e9d34ee50d_r.jpg"/>
Unlike a programming language that requires knowledge of loops, variables, and other concepts, CSS is pretty easy to pick up. Maybe it’s because of this that it has gained the reputation of being simple. It is simple in the sense of “not complex”, but that doesn’t mean it’s easy.Mistaking “simple” for “easy” will only lead to heartache. -- by @Jeremy Keith
這就是為什么寫得好CSS不多見。
而對于Web頁面和Web應用而言,他的構層主要由HTML、CSS和JavaScript。其中HTML和CSS的關系又是緊密相連:
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110856569.jpg" data-caption="" data-size="normal" data-rawwidth="1338" data-rawheight="982" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110857373.jpg" class="origin_image zh-lightbox-thumb" width="1338" data-original="https://pic1.zhimg.com/v2-623bc8f730ea257e7bb7ddd3a8f3e8f4_r.jpg"/>
簡單地說:
那么首要解決的問題就是寫好HTML結構,寫好HTML結構,寫好HTML結構;定義好的類名,定義好的類名,定義好的類名。
怎么做到呢?徒手擼出類似Bootstrap的HTML:
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110858742.jpg" data-caption="" data-size="normal" data-rawwidth="2156" data-rawheight="904" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110859214.jpg" class="origin_image zh-lightbox-thumb" width="2156" data-original="https://pic1.zhimg.com/v2-fbcef8c2ae794c77c64940d2c4c87450_r.jpg"/>
比如寫個Button:
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110900377.jpg" data-caption="" data-size="normal" data-rawwidth="1740" data-rawheight="692" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110902559.jpg" class="origin_image zh-lightbox-thumb" width="1740" data-original="https://pic3.zhimg.com/v2-4220af0fb4d6802bf93dc81aacfd9afd_r.jpg"/>
就我個人而言,HTML結構都喜歡寫成Bootstrap這種。
Bootstrap?
getbootstrap.com
另外就是在寫組件或者HTML結構時還可以參照 "Accessible Rich Internet Applications "規范中的Widget部分:
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110903708.jpg" data-caption="" data-size="normal" data-rawwidth="1684" data-rawheight="1270" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110906468.jpg" class="origin_image zh-lightbox-thumb" width="1684" data-original="https://pic3.zhimg.com/v2-e06a5e8610c65467ece6594fc717d04a_r.jpg"/>
Accessible Rich Internet Applications (WAI-ARIA) 1.1?
www.w3.org
另外,還可以參考一些優秀的網站,Frameworks,庫。這樣可以提高自己在HTML方面的能力,比如結構的管理,類名命名。更多的話可以閱讀一些關于HTML語義化的文章。
回到CSS上來。很多擼CSS的同學常常會犯的問題:
選擇器運用不好
選擇器的使用在CSS中絕對算是重中之重。CSS發展到目前為止,選擇器已經非常的成熟了,可以實現很多類似于早期jQuery的選擇器功能。
如果前期的HTML寫的足夠好,在選擇器定位到目標元素時就會變得較為輕松,而且可讀性也會較強。很同學用不好選擇器,除了不知道怎么用之外,還有一個更重要的原因,選擇器權重不理解。
所以說,要用好選擇器,就需要知道 CSS選擇器是怎么一回事,CSS選擇器權重如何計算
有關于選擇器相關的教程網上也很多,這里列幾篇:
CSS3 選擇器--基本選擇器_css3選擇器, 基本選擇器, CSS選擇器 教程_w3cplus?
www.w3cplus.com
CSS3 選擇器--屬性選擇器_css3選擇器, 屬性選擇器, CSS選擇器 教程_w3cplus?
www.w3cplus.com
CSS3 選擇器--偽類選擇器_css3選擇器, 偽類選擇器, CSS選擇器 教程_w3cplus?
www.w3cplus.com
CSS選擇器的優化_基本選擇器, CSS選擇器 教程_w3cplus?
www.w3cplus.com
再聊CSS的屬性選擇器_CSS, CSS選擇器 教程_w3cplus?
www.w3cplus.com
初探CSS 選擇器Level 4?
www.w3cplus.com
你應該知道的一些事情--CSS權重_CSS選擇器 教程_w3cplus?
www.w3cplus.com
使用CSS Mod Queries控制選擇器范圍?
www.w3cplus.com
屬性了解不到位
CSS的屬性事實上并不是非常的復雜,但他們的組合就會讓很多人感到頭痛了。如果希望不頭痛就需要對CSS的屬性有所了解。建議可以從相關規范中獲取:
All Standards and Drafts?
www.w3.org
而CSS中較為重要的幾個功能模塊:
選擇器模塊:
Selectors Level 4?
www.w3.org
盒模型
CSS Box Model Module Level 3?
www.w3.org
特別是邏輯盒模型的出現,將會讓很多CSSer更為頭痛,拿下圖來對比一下:
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110908744.jpg" data-caption="" data-size="normal" data-rawwidth="4096" data-rawheight="1476" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110909991.jpg" class="origin_image zh-lightbox-thumb" width="4096" data-original="https://pic1.zhimg.com/v2-b8c079e508817f0d8ec4b7021a0e936d_r.jpg"/>
CSS的邏輯屬性對盒模型帶來的變化_CSS, CSS邏輯屬性 教程_w3cplus?
www.w3cplus.com
布局模塊:
CSS Flexible Box Layout Module Level 1?
www.w3.org
CSS Inline Layout Module Level 3?
www.w3.org
CSS Grid Layout Module Level 2?
www.w3.org
CSS Multi-column Layout Module Level 1?
www.w3.org
CSS Layout API Level 1?
www.w3.org
Layout_入門 精通 教程_w3cplus?
www.w3cplus.com
值、單位和顏色
CSS Values and Units Module Level 4?
www.w3.org
CSS Values and Units Module Level 3?
www.w3.org
CSS Color Module Level 3?
www.w3.org
圖解CSS:CSS 的值和單位_CSS, 圖解CSS, 長度單位 教程_w3cplus?
www.w3cplus.com
定位
CSS Positioned Layout Module Level 3?
www.w3.org
position_入門 精通 教程_w3cplus?
www.w3cplus.com
層疊和繼承
圖解CSS:CSS層疊和繼承_CSS, 圖解CSS 教程_w3cplus?
www.w3cplus.com
聊聊CSS中的層疊相關概念_CSS, z-index, BFC 教程_w3cplus?
www.w3cplus.com
transform/transition/animation相關的
CSS Transforms Module Level 1?
www.w3.org
CSS Transitions?
www.w3.org
CSS Animations Level 1?
www.w3.org
https://www.w3cplus.com/blog/tags/95.html?
www.w3cplus.com
transition_入門 精通 教程_w3cplus?
www.w3cplus.com
Web動畫_入門 精通 教程_w3cplus?
www.w3cplus.com
另外還有比較新的,比如:
看到這些,估計為什么寫不出好的CSS有一定的原因所在了。剛才也說過,同樣一個效果,可能會有N種組合方式,甚至 同一個人在不同時間寫同一個效果都會有N種組合方式。因為CSS就是一種七巧板
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110910624.jpg" data-caption="" data-size="normal" data-rawwidth="427" data-rawheight="241" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110911655.jpg" class="origin_image zh-lightbox-thumb" width="427" data-original="https://pic4.zhimg.com/v2-a36a707ee5b6b47d19374321eb321952_r.jpg"/>
不夠成體系
其實寫CSS還是有很多方法論的,比如有名的:
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110913961.jpg" data-caption="" data-size="normal" data-rawwidth="1000" data-rawheight="366" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110915803.jpg" class="origin_image zh-lightbox-thumb" width="1000" data-original="https://pic3.zhimg.com/v2-d06fb01e70c923c3417cf86a677a003e_r.jpg"/>
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110916649.jpg" data-caption="" data-size="normal" data-rawwidth="1000" data-rawheight="366" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110917647.jpg" class="origin_image zh-lightbox-thumb" width="1000" data-original="https://pic4.zhimg.com/v2-78e9299ba1786633fd50caded72bc528_r.jpg"/>
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110919127.jpg" data-caption="" data-size="normal" data-rawwidth="1108" data-rawheight="454" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110920572.jpg" class="origin_image zh-lightbox-thumb" width="1108" data-original="https://pic4.zhimg.com/v2-e3a87508fce71a0fdf172af2e4ea5fb7_r.jpg"/>
除了前面提到的,還有其他的類似方法,比如BEM、SUITCSS、MCSS、AMCSS等。
借助這些優秀的方法論,可以讓你的CSS變得更優雅些:
CSS架構_入門 精通 教程_w3cplus?
www.w3cplus.com
借助工具來幫你
到目前為止,寫CSS不僅僅局限于CSS,可以使用一些CSS處理器或其他的工具來幫更簡單的寫CSS。
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110921370.jpg" data-caption="" data-size="normal" data-rawwidth="914" data-rawheight="334" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110923285.jpg" class="origin_image zh-lightbox-thumb" width="914" data-original="https://pic4.zhimg.com/v2-ab2c7ea061aa5ba581a2ddf3924e7b04_r.jpg"/>
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110924812.jpg" data-caption="" data-size="normal" data-rawwidth="720" data-rawheight="719" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110925435.jpg" class="origin_image zh-lightbox-thumb" width="720" data-original="https://pic4.zhimg.com/v2-fa64edf314813f1882d557d5c997e8ce_r.jpg"/>
平時也可以收集一些幫你擼碼的利器
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110927133.jpg" data-caption="" data-size="normal" data-rawwidth="790" data-rawheight="926" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110928547.jpg" class="origin_image zh-lightbox-thumb" width="790" data-original="https://pic2.zhimg.com/v2-24f41e680eb311c8dff575981f76692a_r.jpg"/>
tools_入門 精通 教程_w3cplus?
www.w3cplus.com
眼界不夠高
眼界不夠高,看得少。這方面很簡單,自己多看,多寫。比如Codepen就是一個很好的地方:
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110929265.jpg" data-caption="" data-size="normal" data-rawwidth="2376" data-rawheight="1738" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110930863.jpg" class="origin_image zh-lightbox-thumb" width="2376" data-original="https://pic3.zhimg.com/v2-6e1df27350d76aa0b418f03de2c038c4_r.jpg"/>
今天就寫到這,感覺好長了.....
最后放上早期的一篇分享:
<img src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110932543.jpg" data-caption="" data-size="normal" data-rawwidth="2406" data-rawheight="1436" data-default-watermark-src="http://www.jungjaehyung.com/uploadfile/2024/0806/20240806110933733.jpg" class="origin_image zh-lightbox-thumb" width="2406" data-original="https://pic1.zhimg.com/v2-9468a45677ade79042c584ad2ef6a6f7_r.jpg"/>
寫CSS的姿勢_CSS 教程_w3cplus?
www.w3cplus.com
再給CSSer推薦學習CSS的好去處:
CSS-Tricks?
css-tricks.com
CSS3_入門 精通 教程_w3cplus?
www.w3cplus.com
張鑫旭-鑫空間-鑫生活?
www.zhangxinxu.com
ChokCoco - 博客園?
www.cnblogs.com
另外推薦幾本CSS的書
<img src="https://pic2.zhimg.com/50/v2-e3dca328d69807447af0361dc8e32908_hd.jpg" data-caption="" data-size="normal" data-rawwidth="259" data-rawheight="328" data-default-watermark-src="https://pic3.zhimg.com/50/v2-11cf35a68249c85162f65a4ff2800190_hd.jpg" class="content_image" width="259"/>
<img src="https://pic3.zhimg.com/50/v2-6e2a0e0f95f2c3b77c76e13dc5b73e26_hd.jpg" data-caption="" data-size="normal" data-rawwidth="212" data-rawheight="280" data-default-watermark-src="https://pic4.zhimg.com/50/v2-2615788a104a1d77e1f22da17eb007f0_hd.jpg" class="content_image" width="212"/>
<img src="https://pic3.zhimg.com/50/v2-c29c9d8de69a08ebf4a7a6cf62666a4c_hd.jpg" data-caption="" data-size="normal" data-rawwidth="500" data-rawheight="609" data-default-watermark-src="https://pic2.zhimg.com/50/v2-e9c674761da7667f9b827d75e0d88adf_hd.jpg" class="origin_image zh-lightbox-thumb" width="500" data-original="https://pic3.zhimg.com/v2-c29c9d8de69a08ebf4a7a6cf62666a4c_r.jpg"/>
<img src="https://pic4.zhimg.com/50/v2-28662508c3310dc08173a52d311303bc_hd.jpg" data-caption="" data-size="normal" data-rawwidth="200" data-rawheight="200" data-default-watermark-src="https://pic2.zhimg.com/50/v2-ba483e1a6babac048892d9bf78742ee4_hd.jpg" class="content_image" width="200"/>
<img src="https://pic3.zhimg.com/50/v2-dc4bd14f4ffacd73b7cba1885bc1668b_hd.jpg" data-caption="" data-size="normal" data-rawwidth="200" data-rawheight="200" data-default-watermark-src="https://pic1.zhimg.com/50/v2-7b640425ba95da6b31105599c7fba2f6_hd.jpg" class="content_image" width="200"/>
學習從來不是一個人的事情,要有個相互監督的伙伴,工作需要學習前端或者為了入行、轉行學習前端的伙伴可以私信回復小編“前端”領取全套免費前端學習資料、視頻
EB前端現在是時下較火的編程語言之一,特別是對于自學來說連css的一些權重都不是很了解,針對這種情況小猿圈web前端講師就講講css基礎入門之權重,希望對你的前端學習有一定的幫助。
一、css權重是什么?
css權重指的是css6大基礎選擇符的優先級,優先級高的css樣式會覆蓋優先級底的css樣式,優先級越高說明權重越高,反之亦然。
css6大基礎選擇器:
a)、id選擇器(#box{})
b)、類選擇器(.box{})
c)、屬性選擇器(a[href=http://www.xxx.com])
d)、偽類和偽對象選擇器(:hoevr{}和::after{})
e)、標簽類型選擇器(div{})
f)、通配符選擇器(*{})
優先級順序從大到小:
內聯樣式 > ID 選擇器 > 類選擇器 = 屬性選擇器 = 偽類選擇器 > 元素(類型)選擇器 = 偽元素選擇器
二、css權重計算規則
計算css權重是有一定規則的,根據w3c制定的css規范,css權重計算規則如下:
a)、計算選擇符中的id選擇器的數量一個id選擇器為一個a,一個a為100
b)、計算選擇符中的類選擇器、屬性選擇器以及偽類選擇器的數量一個類選擇器、屬性選擇器以及偽類選擇器為一個b,一個b為10
c)、計算標簽類型選擇器和偽對象選擇器的數量一個標簽類型選擇器、偽對象選擇器為一個c,一個c為1
d)、忽略通配符選擇器通配符選擇器忽略不計
如圖是一個css選擇器權重的例子:
如果兩個選擇符的權重相同,則可依照”就進原則”來判斷,最后定義的選擇符會被采用。但盡量避免出現這種依靠定義的順序決定選擇符優先級的情況,因為在后續的維護中很難保證定義的順序不會被打亂。
小猿圈web前端講師認為:授之以魚更授之以漁,想要學好web前端首先需要就是端正自己的學習態度,明確學習目標,這樣才能堅持學習。想要了解更多關于前端方面的小伙伴,可以關注小猿圈每天的動態,會不定期更新互聯網編程知識,希望對你的學習有一定的幫助。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。