Missed the action at this year's Chrome Dev Summit? Catch up with our playlist on YouTube. Watch now.

減少樣式計算的範圍與複雜性

透過新增和移除元素、變更屬性、類別,或透過動畫來變更 DOM ,都會導致瀏覽器重新計算元素樣式 -- 在許多情況下 -- 為網頁或部分網頁執行版面配置 (或自動重排) 。 這個過程叫做已運算樣式計算

TL;DR

  • 降低您的選取器的複雜性;使用以類別為中心的方法,例如 BEM。
  • 降低樣式計算必須計算的元素數目。

運算樣式的第一部分是建立一組符合的選取器 -- 這本質上是指瀏覽器要弄明白哪些類別、虛擬選取器和 ID 適用於任何特定的元素。

這一過程的第二部分涉及從符合的選取器取得所有樣式規則,並弄清楚元素具有什麼最終樣式。 在 Blink 中 (Chrome和 Opera 的轉譯引擎),這些過程就時下而言,至少在成本上大致相當:

用於計算元素的已運算樣式的大約 50% 時間,會用來比對選取器,而另一半的時間則用於從符合的規則,建構 RenderStyle (已運算樣式的呈現)。

Rune Lillesveen, Opera / Blink 中的樣式無效判定

降低您的選取器的複雜性

在最簡單的案例中,您僅以一個類別,參照您 CSS 中的一個元素:

.title {
  /* styles */
}

但是,在任何專案成長的同時,這可能會導致更複雜的 CSS,結果您可能會看到如下的選取器:

.box:nth-last-child(-n+1) .title {
  /* styles */
}

若想要知道樣式有套用的必要性,瀏覽器必須詢問「這個元素所帶的標題類別的父項,會剛好是帶有方塊類別的第 -n +1 個子項元素嗎?」要弄清楚這個問題 可能 要花很多時間,視使用的選取器和討論中的瀏覽器而定。 反之,選取器的預期行為可變更為一個類別:

.final-box-title {
  /* styles */
}

您大可質疑類別名稱的問題,但對瀏覽器而言,這項工作變得簡單多了。 在前一版中,例如若要知道該元素是同類型的最後一個,瀏覽器必須先知道所有其他元素的一切,以及是否有任何將成為第 n 個最後子項的元素緊接其後,但這個過程的成本可能大幅高於只要類別符合,就配對選取器給元素的做法。

降低樣式化的元素數目

另一項效能考量 -- 通常是 許多樣式更新的更重要因素 -- 則是當元素變更時,所必須執行的驚人工作量。

一般來說,計算元素的已運算樣式的最糟情況成本,等於元素數目乘以選取器數目,因為每個元素需要針對每個樣式至少檢查一次,以查看它是否符合。

樣式計算經常可以直接鎖定於幾個元素,而不必將一整個網頁判定無效。 在最新瀏覽器中,這往往不會帶來什麽問題,因為瀏覽器不一定需要檢查可能受變更影響的所有元素。 在另一方面,較舊的瀏覽器,不一定已針對這樣的任務進行最佳化。 您應該儘可能 降低無效判定的元素數目

測量您的樣式重新計算成本

測量樣式重新計算成本的最簡單且最好的方法是使用 Chrome DevTools 的「時間軸」模式。 若要開始,開啟 DevTools、前往「時間軸」標籤、點擊「錄製」,並與你的網站互動。 當停止錄製時,您會看到如下圖所示。

DevTools 顯示長時間執行的樣式計算。

頂部的長條表示每秒畫面,如您見到長條位在較低線之上 -- 60fps 線 -- 那麼您則有長時間執行的畫面。

在 Chrome DevTools 中放大問題區域。

如果您在如捲動的某個互動中遇到長時間執行的畫面,或某個其他互動,那麼這就值得進一步審查。

如上述情況,如果您有一個很大的紫色區塊,按一下錄製,您就會得到更多的詳細資料。

取得長時間執行樣式計算的詳細資訊。

在這次擷取中,出現了花費剛超過 18ms 的長時間執行「重新計算樣式」事件,而它剛好在捲動時發生,造成體驗中出現明顯的顫動。

如果您按一下事件本身,您可以得到一呼叫堆疊,它會指明您 JavaScript 中觸發此樣式變更的地方。 此外,您還會取得受變化影響的元素數目 (在此例中,剛好超過 400 個元素),以及執行樣式計算的所費時間。 您可以使用此資訊,開始試圖為您的程式碼找到修正。

使用區塊、元素、修改器

BEM (區塊、元素、修改器) 之類的編碼方法,其實會塑造出符合以上效能的選取器,因為它會建議任何事物都要有單一類別,並在您需要階層之處,這也能塑造於類別名稱之內:

.list { }
.list__list-item { }

如果您需要某個修改器,如同在上例中當我們想要為最後子項做些特別處理時,您可以如以下將之加入:

.list__list-item--last-child {}

如果您正在尋找好方法來組織您的 CSS,BEM 真的是很好的起點, 無論是從結構的觀點而言,或是因為樣式查詢的簡化之故。

如果您不喜歡 BEM,仍有其他方法可處理您的 CSS,但效能考量必須和方案的便利性一起評估。

資源