目錄javascript
資料來源: 《webkit技術內幕》css
結構相關類:html
1.StyleRuleBase類: 單個的樣式規則(選擇器+規則體)java
2.StyleSheetContents類: 樣式規則集,其成員-m_childRules是一個StyleRuleBase實例的列表,是1:n的數量關係git
3.CSSStyleSheet類: 成員-m_contents是一個StyleSheetContents實例,是1:1的數量關係github
4.DocumentStyleSheetCollection類: 多種來源的CSSStyleSheet實例(用戶樣式表,網頁做者樣式表,默認樣式表)的歸類列表web
5.Document類:數組
規則匹配處理相關類:瀏覽器
1.RuleSet類: 單個css樣式表經css解釋器以後的結果集,而且按照關鍵選擇器的類型分類函數
2.DocumentRuleSets類: 各類來源的樣式表的合併(用戶樣式表/做者樣式表/默認樣式表)
3.StyleSheetResover類: 規則匹配的主要負責類
樣式規則匹配大體過程
1.StyleResover類以ElementRuleCollector類爲工具,爲指定的元素匹配規則,並將匹配結果保存到RenderStyle對象中,RenderStyle對象由負責該元素渲染的RenderObject對象管理和使用
2.匹配的輸入: StyleResover類中保存的css解釋器的解釋和分類完畢的樣式規則
3.匹配用到的工具類: ElementRuleCollector類
4.被匹配對象: 指定html元素
5.匹配結果: 保存至RenderStyle對象並被RenderObject用於元素渲染
規則匹配的詳細過程
說明:
1.關鍵選擇器: 樣式規則的選擇器字符串中的最右邊選擇器,它是樣式規則在解釋後分類的依據
2.匹配過程:
3.做者樣式匹配詳細過程:(默認樣式,用戶樣式的匹配相似)
匹配規則: 從右向左依次匹配選擇器
前面咱們已經知道解釋以後的樣式規則是分類存放在對象中的,而爲當前元素匹配規則時,也是按id,class,tag,feature順序依次匹配.
下面咱們用僞代碼來解釋匹配的詳細過程:(僞代碼不是真正合理的和實際的代碼)
1.重要參數
//參數e: 指代被匹配的元素 //重要的變量 var Result=[]; //用於保存徹底匹配的結果集
2.工具函數
function firstMatch(property,ruleSet){ //將元素的id/class/tag/feature與idRules/classRules/tagRules/featureRules匹配 //將匹配到的規則以數組返回,未匹配到返回空. } function getS(rule){ //獲取單條rule規則的選擇器數組 } function Match(s,e){ //將選擇器s與元素e匹配 //若是成功匹配則返回true,不然返回false } function leftMatch(rule,e){ //第一次匹配事後,用於處理結果集中單條規則的匹配的函數(調用Match函數) var s = getS(rule); //獲取單條規則的選擇器數組 for(var i=s.length-1;i>=0;i--){ //從右到左依次將選擇器與元素e匹配 var flag = Match(s[i],e); if(!flag){ //一旦某次匹配失敗,函數直接返回 return; } } push(Result,rule); //僅當全部選擇器都匹配成功,即徹底匹配時,纔將該條rule添加到Result } function ruleMatch(firstmatch,e){ //第一次匹配後的處理函數(調用leftMatch函數) if(firstmatch爲空){ //第一次匹配爲空,直接返回 return; } for(var i=0;i<=firstMatch.length-1;i++){ leftMatch(firstMatch[i],e); //第一次匹配不爲空,對每條匹配到的規則調用leftMatch } }
3.id,class,tag,feature匹配的函數及調用順序
//匹配idRules的函數 function idMatch(idRules,e){ var firstmatch = firstMatch(e.id,idRules); ruleMatch(firstmatch,e); } //匹配classRules的函數 function classMatch(classRules,e){ var firstmatch = firstMatch(e.class,classRules); ruleMatch(firstmatch,e); } //匹配tagRules的函數 function tagMatch(tagRules,e){ var firstmatch = firstMatch(e.tag,tagRules); ruleMatch(firstmatch,e); } //匹配featureRules的函數 function featureMatch(featureRules,e){ var firstmatch = firstMatch(e.feature,featureRules); ruleMatch(firstmatch,e); } //函數調用順序 idMatch(idRules,e); classMatch(classRules,e); tagMatch(tagRules,e); featureMatch(featureRules,e);
4.說明
1.選擇器字符串的權重(specifishity)
(1)css中的權重模型(I-S-A-B-C)
其中:
I: 指代該規則是否爲!important規則
S: 指代該規則是否爲內聯樣式規則
A-B-C: 爲內核定義的三類簡單選擇器
基礎部分: A-B-C模型(以webkit爲例)
瀏覽器內核用一個32位二進制數來表示某css規則的權重值,其基礎部分的A-B-C模型是指權重計算的三類增量.
說明:
2.CSS規則權重的計算:
2.涉及到做者樣式,用戶樣式,默認樣式三種樣式來源時的權重規則
通常,網頁開發者和大多數用戶考慮到的只有做者樣式表和默認樣式表(例如:用選擇器*去掉默認樣式中的元素margin和padding),而默認樣式表中不含任何內聯樣式和!important樣式.可是若是咱們考慮上用戶樣式,權重規則可能會有一點不和諧的地方:(優先級從大到小)
用戶樣式!important規則 > 做者樣式!important規則 > 內聯樣式 > 做者樣式普通規則 > 用戶樣式普通規則
上面的優先級鏈中不包含內聯!important規則,是由於通常的!important規則的目的就是爲了之外部樣式覆蓋內聯樣式.
可見, 在普通規則和!important規則上, 兩種樣式表的權重狀況是不一樣的.
可能正是這樣的不和諧,才使得各大瀏覽器都在逐漸廢除用戶樣式吧.可是用戶樣式的實現能夠藉助瀏覽器插件間接實現,不過那又是另一個故事了.
前面說到: 相同屬性設置時,高權重覆蓋低權重.那麼若是兩條規則的權重相同時如何決定哪一個有效哪一個無效呢?
首先,這裏的權重相同有兩層含義:
那麼,權重相同的狀況有下面幾種:
1.同一外部樣式表中的同權重規則
2.不一樣樣式表中的同權重規則(兩部分)
3.元素class屬性爲多個值,且各個值同權重時
css2.1規範指出: 若是兩個聲明的權重,來源都相同,後指定的生效. 經過@import引入的樣式表中的規則被認爲位於父樣式表自身的全部規則以前.
而咱們討論同權重規則的覆蓋,就是對這個後指定的理解與解讀:
下面是一些測試代碼:
/*測試1: 同同樣式表內同權重規則+覆蓋規則與class內值前後順序無關*/ /*html部分: <div class="a b"></div> */ div{ width: 100px; height: 100px; border: 1px solid black; } .b { background-color: blue; } .a { background-color: red; } /*測試結果: 紅色*/
/*測試2: 不一樣樣式表,相同權重規則*/ /*test1:<link>位於<style>以前*/ /*html部分: <link rel="stylesheet" href="csstest2.css"> <div class="a"></div> <style type="text/css"> .a{ background-color: red; } </style> */ div{ width: 100px; height: 100px; border: 1px solid black; } .a { background-color: blue; } /*測試結果: 紅色*/ /*test2:link位於style以後*/ /*html部分: <div class="a"></div> <style type="text/css"> .a{ background-color: red; } </style> <link rel="stylesheet" href="csstest2.css"> */ div{ width: 100px; height: 100px; border: 1px solid black; } .a { background-color: blue; } /*測試結果: 藍色*/ /*test3: ABC覆蓋規則*/ /*html部分: <div class="a"></div> <style type="text/css"> .a{ background-color: blue; } </style> <link rel="stylesheet" href="csstest2.css"> */ /*csstest3.css內容 @charset utf-8; .a { background-color:yellow; } */ @import "csstest3.css"; /*必須註釋掉前面全部的測試內容,不然違反了@import的使用規則*/ div{ width: 100px; height: 100px; border: 1px solid black; } .a { background-color: red; } /*測試結果: 不做註釋: 紅色 註釋csstest2.css: 黃色 註釋csstest2.css和csstest3.css: 藍色 */