瀏覽器要在屏幕上渲染內容,須要先構建 DOM 與 CSSOM 樹。所以,咱們須要確保將 HTML 和 CSS 儘量快地提供給瀏覽器。css
讓咱們從最簡單的可能狀況開始說:一個普通 HTML 網頁,包含一些文字,一張圖片。瀏覽器須要作什麼才能處理這個簡單頁面呢?html
上述整個流程的最終輸出是文檔對象模型,即這個簡單網頁的 「DOM」,瀏覽器使用它完成頁面的全部後續處理。html5
每次瀏覽器處理 HTML 標記,都要完成上述各個步驟:將字節轉換爲字符,確認符號,將符號轉換爲節點,而後構建 DOM 樹。整個過程須要一些時間,處理大量 HTML 時更是如此。瀏覽器
Note網絡
若是您打開 Chrome DevTools,並在頁面加載時錄製時間軸,你能夠看到執行這一步驟所需的實際時間 — 在上例中,將一堆 HTML 字節轉換爲 DOM 樹大約須要 5 毫秒。固然,若是頁面更大(大多數頁面都是如此),這個過程須要的時間估計會更多。在後面建立流暢動畫的章節中,您會看到,若是瀏覽器必須處理大量 HTML,這極可能變成你的瓶頸。數據結構
DOM 樹準備就緒後,咱們是否就有足夠信息在屏幕上渲染頁面了?還不行!DOM 樹捕獲文檔標記的屬性及關係,但沒有告訴咱們元素在渲染時是什麼樣子。這是 CSSOM 的責任,也就是咱們接下來要講的。學習
瀏覽器在構建咱們的簡單頁面 DOM 時,在文檔的 head 部分碰上一個 link 標籤,引用了外部 CSS 樣式表 style.css。瀏覽器預見到它會須要這個資源來渲染頁面,所以會當即發出一個該資源的請求,該請求返回如下內容:字體
body { font-size: 16px } p { font-weight: bold } span { color: red } p span { display: none } img { float: right }
固然,咱們本能夠在 HTML 標記中直接聲明樣式(內聯),可是,將 CSS 與 HTML 分開,咱們就能夠分離關注點:設計人員處理 CSS,開發人員關注 HTML,等等。動畫
與 HTML 同樣,咱們須要將收到的 CSS 規則轉換爲瀏覽器能夠理解、可以處理的東西。所以,咱們再重複一次與處理 HTML 很是類似的過程:編碼
CSS 字節會轉換爲字符,而後轉換爲符號和節點,最後連接進樹狀結構上,即所謂「CSS 對象模型」,縮寫爲 CSSOM:
CSSOM 爲何採用樹狀結構? 在給頁面上的一切對象計算最終的樣式集時,瀏覽器會先從應用給該節點的最通用規則開始(例如,若是節點是 body 元素的子元素,則應用全部 body 樣式),而後,經過應用更具體的規則遞歸細化計算的樣式 - 亦即規則「向下層疊」。
再具體點說,咱們來看一下上面的 CSSOM 樹。body 元素中 span 標記內包含的任何文字均是 16 像素字體大小,紅色文本 - font-size 指令從 body 向下層疊到 span。可是,若是 span 標籤是 paragraph (p) 標籤的子標籤,則它的內容不會顯示。
此外,請注意,上面的樹不是完整的 CSSOM 樹,它只顯示了咱們決定在樣式表中覆蓋的樣式。每一個瀏覽器都會提供一套默認的樣式,也稱爲「用戶代理樣式」 – 即咱們不提供任何自定義樣式時看到的樣式 – 咱們的樣式只是覆蓋這些默認樣式集(例如 默認 IE 樣式)。若是您曾在 Chrome DevTools 中檢查過「計算的樣式」,而且想知道全部樣式從何來,如今您應該知道答案了!
好奇 CSS 處理須要的時間? 在 DevTools 中錄製時間軸,並查找 「Recalculate Style」 事件:與 DOM 解析不一樣,timeline 不顯示單獨的 「Parse CSS」 條目,而是在 「Recalculate Style」 這一個事件下一同捕獲解析、CSSOM 樹的構建及計算的樣式的遞歸計算。
處理咱們的小樣式表須要大約 0.6 毫秒,影響網頁上的 8 個元素 – 時間很少,但也會產生成本。只不過,8 個元素從何而來呢?CSSOM 和 DOM 是獨立的數據結構。結果證實,瀏覽器隱藏了一個重要步驟。接下來,讓咱們聊聊將 DOM 與 CSSOM 連接在一塊兒的渲染樹。