瀏覽器工作原理05 [#] 渲染流程(上):HTML、CSS和JavaScript是如何變成頁面的

引用

瀏覽器工作原理與實踐

一、提出問題

在上一篇文章中我們介紹了導航相關的流程,那導航被提交后又會怎么樣呢?就進入了渲染階段。這個階段很重要,了解其相關流程能讓你“看透”頁面是如何工作的,有了這些知識,你可以解決一系列相關的問題,比如能熟練使用開發者工具,因為能夠理解開發者工具里面大部分項目的含義,能優化頁面卡頓問題,使用JavaScript優化動畫流程,通過優化樣式表來防止強制同步布局,等等。

既然它的功能這么強大,那么今天,我們就來好好聊聊渲染流程。

通常,我們編寫好HTML、CSS、JavaScript等文件,經過瀏覽器就會顯示出漂亮的頁面(如下圖所示),但是你知道它們是如何轉化成頁面的嗎?這背后的原理,估計很多人都答不上來。

從圖中可以看出,左邊輸入的是HTML、CSS、JavaScript數據,這些數據經過中間渲染模塊的處理,最終輸出為屏幕上的像素。

這中間的渲染模塊就是我們今天要討論的主題。為了能更好地理解下文,你可以先結合下圖快速抓住HTML、CSS和JavaScript的含義:

從上圖可以看出,HTML的內容是由標記和文本組成。標記也稱為標簽,每個標簽都有它自己的語意,瀏覽器會根據標簽的語意來正確展示HTML內容。比如上面的<p>標簽是告訴瀏覽器在這里的內容需要創建一個新段落,中間的文本就是段落中需要顯示的內容

如果需要改變HTML的字體顏色、大小等信息,就需要用到CSS。CSS又稱為層疊樣式表,是由選擇器和屬性組成,比如圖中的p選擇器,它會把HTML里面<p>標簽的內容選擇出來,然后再把選擇器的屬性值應用到<p>標簽內容上。選擇器里面有個color屬性,它的值是red,這是告訴渲染引擎把<p>標簽的內容顯示為紅色

至于JavaScript(簡稱為JS),使用它可以使網頁的內容“動”起來,比如上圖中,可以通過JavaScript來修改CSS樣式值,從而達到修改文本顏色的目的。

搞清楚HTML、CSS和JavaScript的含義后,那么接下來我們就正式開始分析渲染模塊了。

由于渲染機制過于復雜,所以渲染模塊在執行過程中會被劃分為很多子階段,輸入的HTML經過這些子階段,最后輸出像素。我們把這樣的一個處理流程叫做渲染流水線,其大致流程如下圖所示:

按照渲染的時間順序,流水線可分為如下幾個子階段:構建DOM樹、樣式計算、布局階段、分層、繪制、分塊、光柵化和合成。內容比較多,我會用兩篇文章來為你詳細講解這各個子階段。接下來,在介紹每個階段的過程中,你應該重點關注以下三點內容

  • 開始每個子階段都有其輸入的內容;
  • 然后每個子階段有其處理過程;
  • 最終每個子階段會生成輸出內容。

理解了這三部分內容,能讓你更加清晰地理解每個子階段。

二、構建DOM樹

為什么要構建DOM樹呢?這是因為瀏覽器無法直接理解和使用HTML,所以需要將HTML轉換為瀏覽器能夠理解的結構——DOM樹。

這里我們還需要簡單介紹下什么是樹結構,為了更直觀地理解,你可以參考下面我畫的幾個樹結構:

從圖中可以看出,樹這種結構非常像我們現實生活中的“樹”,其中每個點我們稱為節點,相連的節點稱為父子節點。樹結構在瀏覽器中的應用還是比較多的,比如下面我們要介紹的渲染流程,就在頻繁地使用樹結構。

接下來咱們還是言歸正傳,來看看DOM樹的構建過程,你可以參考下圖

從圖中可以看出,構建DOM樹的輸入內容是一個非常簡單的HTML文件,然后經由HTML解析器解析,最終輸出樹狀結構的DOM。

為了更加直觀地理解DOM樹,你可以打開Chrome的“開發者工具”,選擇“Console”標簽來打開控制臺,然后在控制臺里面輸入“document”后回車,這樣你就能看到一個完整的DOM樹結構,如下圖所示:

圖中的document就是DOM結構,你可以看到,DOM和HTML內容幾乎是一樣的,但是和HTML不同的是,DOM是保存在內存中樹狀結構,可以通過JavaScript來查詢或修改其內容。

那下面就來看看如何通過JavaScript來修改DOM的內容,在控制臺中輸入:

document.getElementsByTagName("p")[0].innerText = "black"

這行代碼的作用是把第一個<p>標簽的內容修改為black,具體執行結果你可以參考下圖:

從圖中可以看出,在執行了一段修改第一個<p>標簽的JavaScript代碼后,DOM的第一個p節點的內容成功被修改,同時頁面中的內容也被修改了

好了,現在我們已經生成DOM樹了,但是DOM節點的樣式我們依然不知道,要讓DOM節點擁有正確的樣式,這就需要樣式計算了

三、樣式計算

樣式計算的目的是為了計算出DOM節點中每個元素的具體樣式,這個階段大體可分為三步來完成

# 1. 把CSS轉換為瀏覽器能夠理解的結構

那CSS樣式的來源主要有哪些呢?你可以先參考下圖:

從圖中可以看出,CSS樣式來源主要有三種:

  • 通過link引用的外部CSS文件

  • <style>標記內的 CSS

  • 元素的style屬性內嵌的CSS

  • 和HTML文件一樣,瀏覽器也是無法直接理解這些純文本的CSS樣式,所以當渲染引擎接收到CSS文本時,會執行一個轉換操作,將CSS文本轉換為瀏覽器可以理解的結構——styleSheets。

  • 為了加深理解,你可以在Chrome控制臺中查看其結構,只需要在控制臺中輸入document.styleSheets,然后就看到如下圖所示的結構

從圖中可以看出,這個樣式表包含了很多種樣式,已經把那三種來源的樣式都包含進去了。當然樣式表的具體結構不是我們今天討論的重點,你只需要知道渲染引擎會把獲取到的CSS文本全部轉換為styleSheets結構中的數據,并且該結構同時具備了查詢和修改功能,這會為后面的樣式操作提供基礎

# 2. 轉換樣式表中的屬性值,使其標準化

現在我們已經把現有的CSS文本轉化為瀏覽器可以理解的結構了,那么接下來就要對其進行屬性值的標準化操作。

要理解什么是屬性值標準化,你可以看下面這樣一段CSS文本

body { font-size: 2em }
p {color:blue;}
span  {display: none}
div {font-weight: bold}
div  p {color:green;}
div {color:red; }

可以看到上面的CSS文本中有很多屬性值,如2em、blue、bold,這些類型數值不容易被渲染引擎理解,所以需要將所有值轉換為渲染引擎容易理解的、標準化的計算值,這個過程就是屬性值標準化。

那標準化后的屬性值是什么樣子的?

從圖中可以看到,2em被解析成了32px,red被解析成了rgb(255,0,0),bold被解析成了700……

# 3. 計算出DOM樹中每個節點的具體樣式

現在樣式的屬性已被標準化了,接下來就需要計算DOM樹中每個節點的樣式屬性了,如何計算呢?

這就涉及到CSS的繼承規則和層疊規則了。

首先是CSS繼承。CSS繼承就是每個DOM節點都包含有父節點的樣式。這么說可能有點抽象,我們可以結合具體例子,看下面這樣一張樣式表是如何應用到DOM節點上的

body { font-size: 20px }
p {color:blue;}
span  {display: none}
div {font-weight: bold;color:red}
div  p {color:green;}

這張樣式表最終應用到DOM節點的效果如下圖所示:

從圖中可以看出,所有子節點都繼承了父節點樣式。比如body節點的font-size屬性是20,那body節點下面的所有節點的font-size都等于20。

為了加深你對CSS繼承的理解,你可以打開Chrome的“開發者工具”,選擇第一個“element”標簽,再選擇“style”子標簽,你會看到如下界面

這個界面展示的信息很豐富,大致可描述為如下

  • 首先,可以選擇要查看的元素的樣式(位于圖中的區域2中),在圖中的第1個區域中點擊對應的元素元素,就可以了下面的區域查看該元素的樣式了。比如這里我們選擇的元素是<p>標簽,位于html.body.div.這個路徑下面
  • 其次,可以從樣式來源(位于圖中的區域3中)中查看樣式的具體來源信息,看看是來源于樣式文件,還是來源于UserAgent樣式表。這里需要特別提下UserAgent樣式,它是瀏覽器提供的一組默認樣式,如果你不提供任何樣式,默認使用的就是UserAgent樣式。
  • 最后,可以通過區域2和區域3來查看樣式繼承的具體過程。

以上就是CSS繼承的一些特性,樣式計算過程中,會根據DOM節點的繼承關系來合理計算節點樣式。

樣式計算過程中的第二個規則是樣式層疊。層疊是CSS的一個基本特征,它是一個定義了如何合并來自多個源的屬性值的算法。它在CSS處于核心地位,CSS的全稱“層疊樣式表”正是強調了這一點。關于層疊的具體規則這里就不做過多介紹了,網上資料也非常多,你可以自行搜索學習

總之,樣式計算階段的目的是為了計算出DOM節點中每個元素的具體樣式,在計算過程中需要遵守CSS的繼承和層疊兩個規則。這個階段最終輸出的內容是每個DOM節點的樣式,并被保存在ComputedStyle的結構內。

如果你想了解每個DOM元素最終的計算樣式,可以打開Chrome的“開發者工具”,選擇第一個“element”標簽,然后再選擇“Computed”子標簽,如下圖所示:

上圖紅色方框中顯示了html.body.div.p標簽的ComputedStyle的值。你想要查看哪個元素,點擊左邊對應的標簽就可以了

四、布局階段

現在,我們有DOM樹和DOM樹中元素的樣式,但這還不足以顯示頁面,因為我們還不知道DOM元素的幾何位置信息。那么接下來就需要計算出DOM樹中可見元素的幾何位置,我們把這個計算過程叫做布局。

Chrome在布局階段需要完成兩個任務:創建布局樹和布局計算

# 1. 創建布局樹

你可能注意到了DOM樹還含有很多不可見的元素,比如head標簽,還有使用了display:none屬性的元素。所以在顯示之前,我們還要額外地構建一棵只包含可見元素布局樹。

我們結合下圖來看看布局樹的構造過程:

從上圖可以看出,DOM樹中所有不可見的節點都沒有包含到布局樹中。

為了構建布局樹,瀏覽器大體上完成了下面這些工作

  • 遍歷DOM樹中的所有可見節點,并把這些節點加到布局中;
  • 而不可見的節點會被布局樹忽略掉,如head標簽下面的全部內容,再比如body.p.span這個元素,因為它的屬性包含 dispaly:none,所以這個元素也沒有被包進布局樹

# 2. 布局計算

現在我們有了一棵完整的布局樹。那么接下來,就要計算布局樹節點的坐標位置了。布局的計算過程非常復雜,我們這里先跳過不講,等到后面章節中我再做詳細的介紹。

在執行布局操作的時候,會把布局運算的結果重新寫回布局樹中,所以布局樹既是輸入內容也是輸出內容,這是布局階段一個不合理的地方,因為在布局階段并沒有清晰地將輸入內容和輸出內容區分開來。針對這個問題,Chrome團隊正在重構布局代碼,下一代布局系統叫LayoutNG,試圖更清晰地分離輸入和輸出,從而讓新設計的布局算法更加簡單。

五、總結

從圖中可以看出,本節內容我們介紹了渲染流程的前三個階段:DOM生成、樣式計算和布局。要點可大致總結為如下:

  • 瀏覽器不能直接理解HTML數據,所以第一步需要將其轉換為瀏覽器能夠理解的DOM樹結構;
  • 生成DOM樹后,還需要根據CSS樣式表,來計算出DOM樹所有節點的樣式;
  • 最后計算DOM元素的布局信息,使其都保存在布局樹中。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/84268.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/84268.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/84268.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

DrissionPage爬蟲包實戰分享

一、爬蟲 1.1 爬蟲解釋 爬蟲簡單的說就是模擬人的瀏覽器行為&#xff0c;簡單的爬蟲是request請求網頁信息&#xff0c;然后對html數據進行解析得到自己需要的數據信息保存在本地。 1.2 爬蟲的思路 # 1.發送請求 # 2.獲取數據 # 3.解析數據 # 4.保存數據 1.3 爬蟲工具 Dris…

android 布局小知識點 隨記

1. 布局屬性的命名前綴規律 與父容器相關的前綴 layout_alignParent&#xff1a;相對于父容器的對齊方式。 例如&#xff1a;layout_alignParentTop"true"&#xff08;相對于父容器頂部對齊&#xff09;。layout_margin&#xff1a;與父容器或其他控件的邊距。 例如…

GeoDrive:基于三維幾何信息有精確動作控制的駕駛世界模型

25年5月來自北大、理想汽車和 UC Berkeley 的論文“GeoDrive: 3D Geometry-Informed Driving World Model with Precise Action Control”。 世界模型的最新進展徹底改變動態環境模擬&#xff0c;使系統能夠預見未來狀態并評估潛在行動。在自動駕駛中&#xff0c;這些功能可幫…

Java高頻面試之并發編程-25

hello啊&#xff0c;各位觀眾姥爺們&#xff01;&#xff01;&#xff01;本baby今天又來報道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面試官&#xff1a;CAS都有哪些問題&#xff1f;如何解決&#xff1f; CAS 的問題及解決方案 CAS&#xff08;Compare and Swap&#xff0…

從碳基羊駝到硅基LLaMA:開源大模型家族的生物隱喻與技術進化全景

在人工智能的廣袤版圖上&#xff0c;一場從生物學羊駝到數字智能體的奇妙轉變正在上演。Meta推出的LLaMA(Large Language Model Meta AI)系列模型&#xff0c;不僅名字源自美洲駝(llama)&#xff0c;更以其開源特性和強大性能&#xff0c;引領了開源大模型社區的“駝類大爆發”…

可下載舊版app屏蔽更新的app市場

軟件介紹 手機用久了&#xff0c;app越來越臃腫&#xff0c;老手機卡頓成常態。這里給大家推薦個改善老手機使用體驗的方法&#xff0c;還能幫我們卸載不需要的app。 手機現狀 如今的app不斷更新&#xff0c;看似在優化&#xff0c;實則內存占用越來越大&#xff0c;對手機性…

Python_day47

作業&#xff1a;對比不同卷積層熱圖可視化的結果 一、不同卷積層的特征特性 卷積層類型特征類型特征抽象程度對輸入的依賴程度低層卷積層&#xff08;如第 1 - 3 層&#xff09;邊緣、紋理、顏色、簡單形狀等基礎特征低高&#xff0c;直接與輸入像素關聯中層卷積層&#xff08…

比較數據遷移后MySQL數據庫和達夢數據庫中的表

設計一個MySQL數據庫和達夢數據庫的表數據比較的詳細程序流程&#xff0c;兩張表是相同的結構&#xff0c;都有整型主鍵id字段&#xff0c;需要每次從數據庫分批取得2000條數據&#xff0c;用于比較&#xff0c;比較操作的同時可以再取2000條數據&#xff0c;等上一次比較完成之…

GC1808高性能24位立體聲音頻ADC芯片解析

1. 芯片概述 GC1808是一款24位立體聲音頻模數轉換器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采樣率&#xff0c;集成Δ-Σ調制器、數字抗混疊濾波器和高通濾波器&#xff0c;適用于高保真音頻采集場景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…

Linux 文本比較與處理工具:comm、uniq、diff、patch、sort 全解析

在類 UNIX 操作系統&#xff0c;特別是 Linux 系統中&#xff0c;命令行提供了一整套強大的文本處理工具&#xff0c;這些工具對于文件差異對比、內容篩選、文本排序以及源代碼管理尤為重要。今天&#xff0c;我們將結合真實示例&#xff0c;深入介紹并實戰演示 comm、uniq、di…

6月6日day46打卡

通道注意力(SE注意力) 知識點回顧&#xff1a; 不同CNN層的特征圖&#xff1a;不同通道的特征圖什么是注意力&#xff1a;注意力家族&#xff0c;類似于動物園&#xff0c;都是不同的模塊&#xff0c;好不好試了才知道。通道注意力&#xff1a;模型的定義和插入的位置通道注意力…

前端技能包

ES6 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body><script>// 變量定義var a1;let b5; // 現在使用let 定義變量// 對象解構let person{&quo…

大數據(1) 大數據概述

一、大數據時代 1.三次信息化浪潮 二、什么是大數據 1.四個特點 4V&#xff1a;數據量&#xff08;Volume&#xff09;大、數據類型&#xff08;Variety&#xff09;繁多、處理速度&#xff08;Velocity&#xff09;快、價值密度&#xff08;Value&#xff09;低 三、大數據…

element-plus 單選組件 el-radio,選不上,又沒報錯,直接復制官網也不行解決方案

在使用 Vue 框架開發項目時&#xff0c;Element UI 是常用的組件庫。最近在開發中遇到了 Element 單選框組件el-radio的雙向綁定問題&#xff0c;直接復制element官網上的的案例下來也是不得&#xff0c;經過調試和探索&#xff0c;終于找到了解決方案&#xff0c;特此記錄分享…

使用 Amazon Q Developer CLI 快速搭建各種場景的 Flink 數據同步管道

在 AI 和大數據時代&#xff0c;企業通常需要構建各種數據同步管道。例如&#xff0c;實時數倉實現從數據庫到數據倉庫或者數據湖的實時復制&#xff0c;為業務部門和決策團隊分析提供數據結果和見解&#xff1b;再比如&#xff0c;NoSQL 游戲玩家數據&#xff0c;需要轉換為 S…

開疆智能Ethernet/IP轉Modbus網關連接質量流量計配置案例

首先設置modbus從站的485參數&#xff0c;確保網關和從站的485參數保持一致。 設置完成后打開網關配置軟件并新建項目 先設置網關在Ethernet一側的IP地址以及數據轉換長度。 設置網關的Modbus參數如波特率9600無校驗8數據位&#xff08;無校驗選8&#xff0c;有校驗選9&#xf…

多智能體MPE環境遇到的若干問題

最近學習MADDPG算法&#xff0c;用MPE環境來測試算法性能。于是便下載了pettingzoo包&#xff0c;運行了simple_tag_v3環境&#xff0c;此環境中有獵人、逃亡者和障礙物。 問題1: MPE中的simple_tag_v3環境&#xff0c;在渲染時看似移動的問題 由于相機視角跟隨導致的視覺錯覺…

[特殊字符] FFmpeg 學習筆記

一、FFmpeg 簡介 FFmpeg 是一個開源跨平臺的視頻和音頻處理工具&#xff0c;支持錄制、轉換、流處理等功能。 官網&#xff1a;https://ffmpeg.org 安裝命令&#xff08;macOS&#xff09;&#xff1a; brew install ffmpeg二、基本命令結構 ffmpeg -i 輸入文件 [參數] 輸出…

leetcode Top100 238. 除自身以外數組的乘積|數組系列

題目鏈接&#xff1a;238. 除自身以外數組的乘積 - 力扣&#xff08;LeetCode&#xff09; 238. 除自身以外數組的乘積|數組系列 給你一個整數數組 nums&#xff0c;返回 數組 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘積 。 題目數據 …

【Liunx專欄_6】Linux線程概念與控制

目錄 1、線程是什么&#xff1f;通過一個圖來理解……2、Linux進程和線程&#xff1f;2.1、之間的關系和區別2.2、線程的優缺點&#xff1f; 3、線程的創建3.1、POSIX線程庫3.2、創建線程3.3、PS查看運行的線程 4、線程的終止5、線程的等待6、線程分離7、線程封裝 1、線程是什么…