瀏覽器渲染過程:javascript
<img>
標籤引用了一張圖片,向服務器發出請求。此時瀏覽器不會等到圖片下載完,而是繼續渲染後面的代碼;<div><span><ul><li>
們,「大夥兒收拾收拾行李,咱得從新來過……」,瀏覽器向服務器請求了新的CSS文件,從新渲染頁面。簡單來講,瀏覽器渲染一共有五步,
1.解析HTML標籤,構建DOM樹。css
2.解析CSS標籤,構建CSSOM樹。
咱們已經看到html解析器碰到腳本後會作的事情,接下來咱們看下html解析器碰到樣式表會發生的狀況
js會阻塞解析,由於它會修改文檔(document)。css不會修改文檔的結構,若是這樣的話,彷佛看起來css樣式不會阻塞瀏覽器html解析。可是事實上 css樣式表是阻塞的。阻塞是指當cssom樹創建好以後纔會進行下一步的解析渲染。html
全部的樣式表都會被解析成cssom對象模型(就和dom樹同樣展示結構),每個頁面element都會被許多css規則匹配
- 匹配順序:origin => weight => specificity
- css origin
-做者自定義
-瀏覽器使用者定義
-userAgent 定義
- css weight
-normal weight
-!important weight
- css specificity (咱們最應該關注的點)
注意:!important 已經被css的做者引入了瀏覽器,用來覆蓋頁面樣式。
原本這個方式並非給開發者使用的,在樣式表中使用!important 會讓咱們忽略specificity 真正工做的原理。
- specificity 是css使人困惑的主要來源。specificity規則由(a,b,c,d)的規則決定。
-a : 值爲1(當樣式放在style屬性中的時候),0爲其它狀況 -b : id在樣式規則中出現的次數 eg:#slide #hello p的值就是2 -c : class,僞類,和屬性在樣式中出現的次數 eg:input[type=email]值就是2 -d : 標籤個數(tag names)和僞類元素出現的次數 例如: Example: HTML <div id=」sidebar」> <div id=」widget」 class=」class-div」> <span class=」span-class」 style=」color: red」>Hello, world!</span> </div> </div> CSS .span-class { /* Specificity (0, 0, 1, 0) */ color: green; } #sidebar #widget { /* Specificity (0, 2, 0, 0) */ color: orange; } #sidebar { /* Specificity (0, 1, 0, 0) */ color: yellow; } #sidebar .class-div { /* Specificity (0, 1, 1, 0) */ color: blue; } The inline rule, will have a specificity of (1, 0, 0, 0). 接下來的優先級是(0, 2, 0, 0);以此類推 - 使用!important 的樣式覆蓋均可以經過css優先級機制(好比加個樣式等來提升優先級) - 總結: -元素樣式的應用按照以下規則排列 -origin -weight -specificity -order of definition specificity只有在origin和weight一致的狀況下才有效,再次就是定義的順序 最後定義的樣式會覆蓋以前的樣式。 - 在解析css的過程當中,cssom樹並非瀏覽器構建的惟一數據結構,css樣式匹配是件重活 爲了儘量快的加載樣式,每一種最精確的匹配規則都會被加入衆多哈希表中的一張 。 有針對id,class類名,標籤名和一些其餘不符合任何規則的哈希表。 當瀏覽器試圖尋找哪一個樣式表加載到元素上的時候,它不必查看全部的規則,而只須要查看哈希表。 這又引導咱們到另外一個重要的知識:咱們從一個元素開始,尋找它的id,class,標籤等,而後在多個字典中查找他們, 咱們老是匹配**最右邊**的(rightmost)的選擇器,這個選擇器稱爲**主選擇器(key selector).** 這個概念開始的時候可能有些難以理解,可是它對咱們如何寫更快的css規則相當重要。 讓咱們看個例子: HTML <div id=」container1」> … thousands of <a> elements here … <a> … </a> … thousands of <a> elements here … </div> <div id=」container2」> <a class=」a-class」>...</a> </div> 咱們假如要選擇container2種的a標籤 This selector: #container2 a {...} 這個選擇器將會嚴重影響加載性能,若是從左到右讀取,那就是先找到#container2而後再找a標籤 ,然而瀏覽器將會從右往左讀取,它會先讀取全部的a標籤,而後再沿着dom往上走,直到找到#container. 這意味着這個規則會尋找全部的a,可是實際上不少a在#container1之中。 咱們能夠寫一個更有效率的樣式表:#container2 .a-class {...}。 這個特性能夠在javascript或者jquery中獲得很好的發揮: eg:將$(‘#container .class-name’)改成$(‘.class-name’, ‘#container’)能夠很好的性能。 -前者會先去尋找.class-name而後再沿着dom樹尋找#container元素 -後者會先找到#container,而後再沿着子樹尋找.class-name的元素
3.把DOM和CSSOM組合成渲染樹(render tree)。render樹java
4.在渲染樹的基礎上進行佈局,計算每一個節點的幾何結構。
佈局(layout):定位座標和大小,是否換行,各類position, overflow, z-index屬性 ……
5.把每一個節點繪製到屏幕上(painting),正式開畫!jquery