JavaScript 通常是觸發視覺變更的原因。有時,這類變更會直接透過樣式操控進行,有時則會透過計算產生視覺變化,例如搜尋或排序資料。JavaScript 執行時間過長或不當,是造成效能問題的常見原因,因此您應盡可能減少這類情況的影響。
樣式計算
新增及移除元素、變更屬性、類別或播放動畫,都會導致瀏覽器重新計算元素樣式,以及部分或整個網頁的版面配置。這個過程稱為「樣式計算」。
瀏覽器會建立一組相符的選取器,藉此判斷哪些類別、虛擬選取器和 ID 適用於任何指定元素,然後開始計算樣式。接著,瀏覽器會處理相符選取器的樣式規則,並找出元素的最終樣式。
樣式重新計算在互動延遲中所扮演的角色
Interaction to Next Paint (INP) 是以使用者為中心的執行階段成效指標,用於評估網頁對使用者輸入內容的整體回應速度。這項指標會測量互動延遲時間,也就是從使用者與網頁互動開始,到瀏覽器繪製下一個影格,向使用者介面顯示相應視覺更新內容為止的時間。
互動的重要環節是繪製下一個影格所需的時間。為呈現下一個影格而執行的轉譯工作包含許多部分,包括在版面配置、繪製和合成工作之前發生的網頁樣式計算。本指南著重於樣式計算成本,但減少互動總算繪時間的任何部分,也能縮短總延遲時間。
降低選取器的複雜度
簡化 CSS 選擇器有助於加快網頁的樣式計算速度。 最簡單的選取器只會使用類別名稱,參照 CSS 中的元素:
.title {
/* styles */
}
不過,隨著專案成長,可能需要更複雜的 CSS,您可能會得到如下的選取器:
.box:nth-last-child(-n+1) .title {
/* styles */
}
為判斷這些樣式如何套用至網頁,瀏覽器必須有效詢問「這是具有 title 類別的元素,且父項具有 box 類別,是父項元素的第 -n+1 個子項嗎?瀏覽器可能需要一段時間才能找出這個值。為簡化這項作業,您可以將選取器變更為更具體的類別名稱:
.final-box-title {
/* styles */
}
這些替代類別名稱可能看起來很奇怪,但可大幅簡化瀏覽器的工作。舉例來說,在舊版中,瀏覽器必須先瞭解所有其他元素,才能判斷某個元素是否為同類型中的最後一個元素,進而判斷該元素是否為 nth-last-child。單純根據類別名稱將選取器與元素比對,在運算上會比這種做法昂貴許多。
減少要設定樣式的元素數量
另一個效能考量 (通常比選取器複雜度更重要) 是元素變更時需要執行的工作量。
一般來說,計算計算元素的樣式時,最糟的情況是元素數量乘以選取器數量,因為瀏覽器至少需要針對每個樣式檢查每個元素一次,確認是否相符。
樣式計算可以直接鎖定幾個元素,不必使整個頁面失效。在現代瀏覽器中,這類問題較少發生,因為瀏覽器不一定需要檢查變更可能影響的所有元素。但舊版瀏覽器不一定會針對這類工作進行最佳化。如有可能,請減少失效元素數量。
評估重新計算樣式的成本
您可透過幾種方式,評估瀏覽器中的樣式重新計算成本。這三種方法各有用途,您可以視需求選擇在開發環境的瀏覽器中進行評估,或是評估網站上實際使用者的這個程序耗時多久。
在 Chrome 開發人員工具中測量樣式重新計算成本
如要評估樣式重新計算的成本,可以使用 Chrome 開發人員工具的「效能」面板。如要開始使用,請按照下列步驟操作:
停止錄製後,您會看到類似下圖的畫面:
頂端的長條是微型火焰圖,也會繪製每秒影格數。活動越靠近時間軸底部,表示瀏覽器繪製影格的速度越快。如果火焰圖在頂端趨於平緩,且上方有紅色長條,表示有工作導致影格執行時間過長。
在捲動等互動期間,長時間執行的影格值得進一步瞭解。如果看到大型紫色方塊,請放大活動並選取任何標示為「重新計算樣式」的工作,進一步瞭解可能耗費大量資源的樣式重新計算工作。
點選事件即可查看呼叫堆疊。如果算繪作業是由使用者互動所致,系統會呼叫觸發樣式變更的 JavaScript。此外,這項資訊也會顯示變更影響的元素數量 (在本例中為 900 多個元素),以及樣式計算所花費的時間。您可以根據這項資訊,開始嘗試修正程式碼。
如果您在執行追蹤前,已在「效能面板」設定中勾選「選取器統計資料」核取方塊,追蹤記錄的底部面板就會有同名的額外分頁。
這個面板會提供每個選取器的相對費用實用資料,方便您找出費用高昂的 CSS 選取器。
詳情請參閱 CSS 選取器統計資料說明文件。
測量實際使用者的樣式重新計算費用
如果您想瞭解網站的實際使用者需要等待多久,才能重新計算樣式,可以使用 Long Animation Frames API 取得相關工具。這項 API 的資料已新增至 JavaScript 程式庫,包括重新計算樣式的時間。web-vitals
如果懷疑互動的呈現延遲是導致網頁 INP 的主要原因,請找出網頁重新計算樣式所花費的時間。詳情請參閱如何測量實際工作環境中的樣式重新計算時間。