如何優化CSS以達網站效能之巔

如何優化CSS以達到網站效能之巔

即使在2021年,網路效能仍然是一個問題。根據HTTP Archive,平均每個頁面需要2MB的下載,發出60多個HTTP請求,在移動裝置上完全載入可能需要18秒。樣式表佔60 kB,分為七個請求,因此在試圖解決效能問題時,它很少是最優先考慮的。

然而,CSS確實有影響,不管它看起來多麼輕微。一旦解決了JavaScript問題,學習正確優化CSS應該是下一個重點。

  1. CSS如何影響頁面效能
  2. CSS效能分析工具
  3. 間接CSS效能優化
  4. 優化CSS載入效能
  5. 優化CSS效能

CSS如何影響頁面效能

CSS看起來是無辜的,但可能需要一些繁重的處理。

CSS渲染阻塞

當瀏覽器遇到<link>標記時,它會在獲取和解析CSS檔案時停止其他瀏覽器下載和處理。

JavaScript也可以阻止瀏覽器渲染,但非同步處理可以通過以下方式實現:

  1. async屬性用於並行下載指令碼,指令碼準備就緒後立即執行。
  2. defer屬性以並行方式下載,然後在DOM就緒時按順序執行。
  3. type="module" 屬性載入ES模組(其行為類似於 defer)。

諸如影象之類的資源通常需要更多頻寬,但可以使用有效的格式,並且可以延遲載入(loading="lazy"屬性),而不阻止瀏覽器渲染。

所有這些都不可能用CSS實現。檔案被快取,因此後續頁面載入應該更快,但渲染阻塞過程仍然存在。

大型CSS檔案處理耗時

樣式表越大,下載和處理CSS物件模型(CSSOM)所需的時間就越長,瀏覽器和JavaScript API可以使用該模型顯示頁面。儘管CSS樣式表比大多數其他網站檔案都小,但它們也不能免於“越小越好”的經驗法則。

CSS檔案增長

識別不再使用的樣式可能很困難,刪除錯誤的樣式可能會對站點造成嚴重破壞。開發人員通常選擇最安全的“保留一切”方法。不再使用的頁面樣式、元件和小部件仍然存在於CSS中。結果如何?檔案大小、複雜性和維護工作量呈指數級增長,使得開發人員刪除冗餘程式碼的可能性越來越小。

樣式表可以引入其他資源

CSS可以使用@import規則引用其他樣式表。這些匯入阻止當前樣式表的處理,並串聯進一步載入 CSS 檔案。

其他資產,如字型和影象,也可以參考。瀏覽器將嘗試優化下載,但當有疑問時,它會立即獲取它們。內襯基座 64 編碼檔案仍需進一步處理。

CSS可以使用@import規則引用其他樣式表。這些匯入會阻止當前樣式表的處理,並以序列方式載入更多CSS檔案。

也可以引用其他資源,例如字型和影象。瀏覽器將嘗試優化下載,但如果有疑問,它將立即獲取下載。內聯base64編碼檔案需要進一步處理。

CSS效果渲染

瀏覽器有三個渲染階段:

  • 佈局layout(或迴流reflow)階段計算每個元素的尺寸,以及它如何影響周圍元素的大小或位置。
  • 繪製paint階段將每個元素的可視部分繪製到單獨的層上:文字、顏色、影象、邊框、陰影等。
  • 渲染層合成(composite draws)根據堆疊上下文、位置、z-indexes等,以正確的順序將每個層繪製到頁面上。

如果不小心,CSS屬性更改和動畫可能會導致所有三個階段重新渲染。某些特性(如陰影和漸變)在計算上也比塊顏色和邊距更昂貴。

CSS效能分析工具

承認您有CSS效能問題是恢復的第一步!找到並解決原因是另一回事。

以下工具和服務(不按任何順序排列)可以幫助您識別程式碼中的樣式瓶頸。

1. 開發人員工具網路面板

Web效能專家花大量時間在開發工具上,尤其是在網路面板上。DevTools是大多數現代瀏覽器的原生版本,不過我們將在示例中使用Google Chrome。

DevTools可以從瀏覽器選單開啟,通常是在“更多工具”>“開發人員工具”中,或者通過鍵盤快捷鍵Ctrl | Cmd+Shift+IF12開啟。

切換到“網路”選項卡,並確保選中“禁用快取”,以防止快取檔案影響報告。您還可以更改限制選項以模擬較慢的行動網路。

重新整理頁面以檢視下載和處理瀑布圖:

DevTools網路面板

DevTools網路面板

任何耗時較長的載入進度條都值得關注,但您應該特別關注堵塞/停滯載入進度條(顯示為白色)。在本例中,高亮顯示的行和所有後續行都無法開始下載,直到在HTML頁面頂部處理了渲染阻塞CSS和JavaScript檔案。

過濾器框允許您顯示或隱藏特定資源:

  • larger-than:<S>: 限制大於<S>的檔案,以位元組(10000)、千位元組(1000 kB)或兆位元組(1 M)表示
  • -larger-than:<S>: 限制小於<S>的檔案
  • -domain:*<.yourdomain.com>:顯示未從主域載入的第三方請求。這些都是網站速度慢的主要原因。

具有優化CSS的高效能頁面通常具有較少的資源,這些資源與短阻塞/暫停條並行載入。

2. WebPageTest

WebGetest提供了類似的網路瀑布檢視,以及許多其他效能圖表:

WebPageTest.org頁面資源載入瀑布圖

WebPageTest.org頁面資源載入瀑布圖

該服務使用基於不同全球位置的裝置,因此您可以評估真實世界的效能和CSS優化。

3. Chrome開發人員工具Lighthouse面板

DevTools Lighthouse面板在基於鉻的瀏覽器中提供,如Chrome、Edge、Brave、Opera和Vivaldi。您可以為移動和桌面裝置生成效能、漸進式Web應用、最佳實踐、可訪問性和搜尋引擎優化報告。

DevTools Lighthouse面板

DevTools Lighthouse面板

該工具提供改進建議,包括優化CSS的方法。並非所有這些都是切實可行的,但最有利於效能提升的點都會被強調。

4. Google PageSpeed Insights

PageSpeed Insights是Lighthouse的線上版本。它的功能較少,但可以在任何瀏覽器中使用,並提供一些可選的見解。

例如,一個樹狀圖顯示了最大的JavaScript資源,其中包含一個覆蓋率指標,該指標指示使用和未使用程式碼的比例:

Google PageSpeed Insights樹狀圖

Google PageSpeed Insights樹狀圖

CSS不會顯示,但JavaScript的數量將影響樣式的效率。

類似的網站速度測試工具包括Pingdom和GTmetrix等十餘個

5. Chrome開發人員工具覆蓋範圍面板

Chromium瀏覽器中的DevTools覆蓋範圍面板有助於定位未使用的CSS(和JavaScript)程式碼。從DevTools更多工具子選單中選擇覆蓋範圍,然後重新整理頁面並瀏覽站點/應用程式:

DevTools覆蓋範圍面板

DevTools覆蓋範圍面板

CSS和JavaScript資產顯示在覆蓋範圍面板中,未使用程式碼的比例用紅色表示。單擊任何檔案以檢視其原始碼,未使用的程式碼在行號欄中以紅色突出顯示。

需要注意的幾件事:

  • 如果重新整理或導航到新頁面,覆蓋率指標將重置,這在WordPress站點上是典型的。只有在瀏覽一個載入內容而不重新整理頁面的單頁應用程式時,未使用的程式碼度量才會降低。
  • 該工具只能解釋在特定時間點使用的CSS。它無法確定小部件是否未被檢視或具有多個JavaScript繫結狀態。

6. Chrome開發人員工具效能監視器

基於Chromium的瀏覽器具有實時效能監視器。同樣,這可以從DevTools的“更多工具”選單中獲得。當您瀏覽頁面、滾動和觸發動畫時,圖表會更新:

DevTools效能監視器

DevTools效能監視器

以下指標對於優化CSS效能特別重要(越低越好):

  • CPU使用率:處理器使用率從0%到100%。
  • 佈局/秒:瀏覽器重新佈局頁面的速率。
  • 樣式重新計算次數/秒:瀏覽器必須重新計算樣式的速率。

如果CSS由於外部因素而陷入困境,其他指標也可能有用(同樣,值越低表示效能越好):

  • JS堆大小:JavaScript物件使用的總記憶體。
  • DOM節點:HTML文件中的元素數。
  • JS事件偵聽器:已註冊的JavaScript事件偵聽器的數量。
  • 文件:資源的數量,包括頁面、CSS檔案、JavaScript模組等。
  • 文件幀:幀、iframe和JavaScript工作指令碼的數量。

7. Chrome開發人員工具效能報告

DevTools效能面板允許您記錄頁面活動以進行進一步分析,並幫助確定效能問題。生成的報告很複雜,許多開發人員都避免使用它們,但它們提供了有價值的資訊。

效能面板的設定圖示允許您設定各種選項,例如降低網路和CPU的速度。您還可以禁用JavaScript示例,以便不記錄詳細的呼叫堆疊。

要開始,請單擊迴圈記錄圖示,載入和/或使用頁面,然後單擊停止按鈕檢視報告:

DevTools效能報告

DevTools效能報告

幾乎所有這些指標都對JavaScript開發人員有用,但CSS優化問題可能從以下方面特別明顯:

  • 頂部紅色條:這表示幀速率顯著下降,這可能會導致效能問題。這在頁面載入開始時是應該的,但是過多的CSS動畫也可能是一個問題。
  • 摘要圖表:高載入、渲染和繪製度量可能表明CSS問題。

間接CSS效能優化

下面的優化程式不會直接解決CSS問題,但它們可以幫助您解決一些效能問題,所需的工作量相對較小。

使用好主機

使用一臺效能良好的主機,使伺服器在物理上更接近使用者,將立即帶來效能優勢。託管計劃各不相同,但主要有三種型別:

  1. 共享託管:您的網站託管在物理伺服器上,可能與數百個其他網站一起。共享磁碟空間、RAM、CPU時間和頻寬。計劃通常成本較低,但效能和可用性會受到其他站點的影響。升級可能是可能的,但您的站點通常會保留在相同的基礎結構上。
  2. 專用託管:您的站點託管在您擁有的一個或多個物理伺服器上。硬體可根據需要進行配置和升級。計劃通常很昂貴,硬體故障仍然存在問題。
  3. 雲託管:雲託管將硬體基礎設施抽象為一組可按需訪問的服務。您的站點可以跨一系列裝置進行配置,以便於升級。

雲託管計劃和價格差異巨大。你可以考慮:

  1. 平臺即服務(PaaS)選項,如虛擬web伺服器和資料庫,或
  2. 軟體即服務(SaaS)選項,提供完全管理的應用程式,如WordPress。

交換主機可以提高效能。它不太可能解決您所有的問題,但它是解決後端和頻寬問題的經濟高效的解決方案。

您還可以考慮使用內容分發網路(CDN)或專業影象和視訊CDN,它可以在地理上更接近使用者的多個位置上分發負載。

利用瀏覽器和伺服器效率功能

大約10%的站點不啟用gzip(或更好的)壓縮,這通常是預設的伺服器選項。通過在傳輸之前壓縮檔案,可以將CSS的大小減少60%或更多。它不會修復低效的CSS,但程式碼會更快到達!

您還應該啟用HTTP/2(或更好),它以較小的二進位制格式傳送資料,壓縮頭,並且可以在同一TCP連線上傳送多個檔案。

最後,確保瀏覽器能夠有效快取CSS和其他檔案。這通常是在HTTP頭中設定ExpiresLast Modified和/或ETag雜湊的問題。

優化CMS

諸如WordPress之類的內容管理系統可以通過主題和外掛進行擴充套件,這些主題和外掛服務於它們自己的CSS。在可能的情況下,您應加快CMS的速度,以:

  1. 刪除未使用的外掛。
  2. 使用更精簡的主題
  3. 啟用快取以防止頁面過度重生成。

優化影象

影象的處理和呈現開銷與HTML、CSS和JavaScript不同,但它們佔頁面重量和可用頻寬的很大一部分。考慮:

  1. 刪除不必要的影象。
  2. 調整大型影象的大小-可能不超過螢幕上最大影象大小的150%。
  3. 使用適當的影象格式-理想情況下是高度壓縮的選項,如WebP或AVIF,但可能是用於徽標和圖表的SVG
  4. 用CSS漸變或其他效果替換影象。
  5. 在HTML的<img>標記中新增寬度和高度屬性,或者使用新的CSS縱橫比屬性,以確保在影象下載之前在頁面上保留適當的空間。

專業的影象CDN可以為您處理一些這方面的工作。有關更多提示,請檢視我們關於如何為Web優化影象的指南

刪除未使用的CSS

最快的樣式是那些您永遠不需要載入或渲染的樣式!嘗試刪除/編輯您不再需要的任何CSS程式碼,例如用於遺留頁面、小部件或框架的CSS程式碼。在較大的網站上,這可能很困難,而且並不總是清楚特定的樣式集是否是必需的。

以下工具在構建時分析HTML和CSS的使用情況,或者通過抓取URL來識別冗餘程式碼。這並不總是足夠的,因此可以設定其他配置,以確保列出由JavaScript和使用者互動觸發的樣式:

還有一個更好的選擇:將CSS拆分為具有明確責任級別的單獨檔案,並相應地編制文件。然後,刪除不必要的樣式變得相當容易。

優化CSS載入效能

並不是所有的CSS都載入相同。謙遜的<link>標籤有許多不總是合乎邏輯的選項和怪癖。

優化Web字型使用

谷歌字型和類似的字型設計商已經徹底改變了網路字型,但幾行字型程式碼可能會佔用數百KB的頻寬。

以下是我們的優化建議:

  1. 僅載入您需要的字型:刪除不使用的字型並檢查是否需要新字型。
  2. 僅載入所需的大小和樣式:大多數字體鑄造廠可以將下載限制為某些字符集(如僅限拉丁語)、權重(厚度)和斜體(傾斜)。瀏覽器可以自動渲染缺少的樣式,儘管結果可能很差。
  3. 限制所需字元:不經常使用的字型可以限制為特定字元。例如,開放式SAN中的標題“CSS教程”可以通過向Google字型查詢字串新增 &text= 引數來定義: fonts.googleapis.com/css?family=Open+Sans&text=CStuorial
  4. 考慮變數字型:可變字型定義了大量的樣式、權重和斜體,使用向量插值。字型檔案稍大一些,但您只需要一個而不需要幾個。recursive font展示了可變字型的靈活性。
  5. 從本地伺服器載入字型:自託管字型比使用代工更有效。需要更少的DNS查詢,並且您可以限制下載到WOFF2,所有現代瀏覽器都支援WOFF2。較舊的瀏覽器(我正在看你IE)可以退回到作業系統字型。
  6. 考慮OS字型:500 KB的Web字型可能看起來很棒,但是如果你切換到通用的Helvetica, Arial, Georgia或者Verdana,有人會注意到嗎?作業系統或網路安全字型是提高效能的簡單方法。

使用適當的字型載入選項

下載和處理Web字型可能需要幾秒鐘的時間。瀏覽器將:

  1. 顯示未設定樣式的文字(FOUT):最初使用第一種可用的回退字型,但一旦web字型準備就緒,就會被替換。
  2. 顯示不可見文字(FOIT):在web字型準備就緒之前,不會顯示任何文字。這是現代瀏覽器中的預設過程,通常需要等待三秒鐘才能恢復為回退字型。

兩者都不理想。CSS font-display屬性和Google Font & display =引數可以選擇一個備選選項:

  • auto:瀏覽器的預設行為(通常為FOIT)。
  • block:有效地阻止。文字最多三秒鐘不可見。沒有字型交換,但文字可能需要時間才能顯示。
  • swap:實際上是FOUT。在web字型可用之前,將使用第一個回退。文字可以立即讀取,但字型交換效果可能會不和諧。Font Style Matcher可用於定義大小類似的回退。
  • fallback:FOIT和FOUT之間的妥協。文字在短時間內不可見(通常為100毫秒),然後使用第一個回退,直到web字型可用。
  • optional:與回退類似,只是沒有發生字型交換。只有在初始期間可用時,才會使用web字型。您的第一個頁面檢視可能會顯示回退字型,後續檢視將使用下載和快取的web字型。

使用swap、fallback或optional可以提高效能。

避免CSS @import

@import at-rule允許將CSS檔案包含在其他檔案中:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/* main.css */
@import url("reset.css");
@import url("grid.css");
@import url("widget.css");
/* main.css */ @import url("reset.css"); @import url("grid.css"); @import url("widget.css");
/* main.css */
@import url("reset.css");
@import url("grid.css");
@import url("widget.css");

這似乎是載入較小元件和字型的有效方法。不幸的是,每個@import都是渲染阻塞,每個檔案都必須按順序載入和解析。

HTML中的多個<link>標記更有效,可以並行載入CSS檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<link rel="stylesheet" href="reset.css">
<link rel="stylesheet" href="grid.css">
<link rel="stylesheet" href="widget.css">
<link rel="stylesheet" href="reset.css"> <link rel="stylesheet" href="grid.css"> <link rel="stylesheet" href="widget.css">
<link rel="stylesheet" href="reset.css">
<link rel="stylesheet" href="grid.css">
<link rel="stylesheet" href="widget.css">

也就是說,這樣更加合理…

串聯和最小化CSS

現代構建工具、CSS前處理器(如Sass)和WordPress外掛可以將所有部分組合到一個大型CSS檔案中。然後刪除不必要的空白、註釋和字元,以將檔案大小減至最小。

使用HTTP/2及更高版本,多個檔案的效能問題較少,但單個檔案只需要一個頭,可以更高效地進行gzip壓縮和快取。

單獨的CSS檔案只有在您有一個或多個頻繁更改的樣式表(可能每週更改幾次)時才實用。即使如此,大部分靜態CSS程式碼仍然可以合併到一個檔案中。有關更多提示,請檢視我們關於如何最小化CSS和JS的教程

避免Base64編碼

工具可以將影象編碼為base64字串,您可以將其用作HTML的<img>標記和CSS背景中的資料URI:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
.background {
background-image: url('data:image/jpg;base64,ABC123...');
}
.background { background-image: url('data:image/jpg;base64,ABC123...'); }
.background {
  background-image: url('data:image/jpg;base64,ABC123...');
}

這會減少HTTP請求的數量,但會損害CSS效能:

  • base64字串可以比其二進位制等效字串大30%。
  • 瀏覽器必須先解碼字串,然後才能使用影象,並且
  • 改變一個影象畫素會使整個CSS檔案無效。

只考慮Base64編碼,如果您使用的是非常小的、不經常改變的影象,其中生成的字串不長於URL。

也就是說,您可以用UTF8編碼可重用的SVG圖示,例如。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
.svgbackground {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600"><circle cx="300" cy="300" r="150" stroke-width="3" stroke="#f00" fill="#ff0" /></svg>');
}
.svgbackground { background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600"><circle cx="300" cy="300" r="150" stroke-width="3" stroke="#f00" fill="#ff0" /></svg>'); }
.svgbackground {
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600"><circle cx="300" cy="300" r="150" stroke-width="3" stroke="#f00" fill="#ff0" /></svg>');
}

刪除CSS Hacks和IE Fallbacks

除非你很不幸,並且有很多Internet Explorer使用者,否則可以從你的CSS中刪除有條件的樣式表和黑客。在大多數情況下,IE使用者仍然會看到一些東西,特別是如果您使用的是“移動優先”設計,預設情況下會顯示更簡單的線性檢視。結果可能不太好,也不會是完美的畫素,但你的開發預算最好是考慮所有使用者的可訪問性。

預載入CSS檔案

<link>標記提供了一個可選的預載入屬性,可以立即開始下載,而不是等待HTML中的真正引入:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My page</title>
<!-- preload styles -->
<link rel="preload" href="/css/main.css" as="style" />
<!-- lots more code -->
<!-- load preloaded styles -->
<link rel="stylesheet" href="/css/main.css" />
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My page</title> <!-- preload styles --> <link rel="preload" href="/css/main.css" as="style" /> <!-- lots more code --> <!-- load preloaded styles --> <link rel="stylesheet" href="/css/main.css" />
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My page</title>
  <!-- preload styles -->
  <link rel="preload" href="/css/main.css" as="style" />
  <!-- lots more code -->
  <!-- load preloaded styles -->
  <link rel="stylesheet" href="/css/main.css" />

這在WordPress和其他CMS中尤其有用,在這些CMS中,外掛可以在頁面下方新增樣式表。

使用關鍵內聯CSS

分析工具可能會建議您“內聯關鍵CSS”或“減少渲染阻塞樣式表”。這可以通過以下方式提高效能:

  • 識別摺疊上方元素使用的基本樣式(頁面載入時可見的樣式)
  • 將關鍵CSS內聯到<head>中的<style>標記中
  • 非同步載入剩餘的CSS以避免渲染阻塞。這可以通過以瀏覽器給予較低優先順序的“print”樣式載入樣式表來實現。載入頁面後,JavaScript將其切換為“all”媒體樣式(<noscript>確保CSS工作時JavaScript不可用):
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<style>
/* critical styles */
body { font-family: sans-serif; color: #111; }
</style>
<!-- load remaining styles -->
<link rel="stylesheet"
href="/css/main.css"
media="print"
onload="this.media='all'">
<noscript>
<link rel="stylesheet" href="/css/main.css">
</noscript>
<style> /* critical styles */ body { font-family: sans-serif; color: #111; } </style> <!-- load remaining styles --> <link rel="stylesheet" href="/css/main.css" media="print" onload="this.media='all'"> <noscript> <link rel="stylesheet" href="/css/main.css"> </noscript>
<style>
/* critical styles */
body { font-family: sans-serif; color: #111; }
</style>
<!-- load remaining styles -->
<link rel="stylesheet" 
     href="/css/main.css"
    media="print" 
   onload="this.media='all'">
<noscript>
  <link rel="stylesheet" href="/css/main.css">
</noscript>

諸如criticalcriticalCSS之類的工具可以幫助提取檢視中元素的樣式。

這項技術顯著提高了績效,提高了審計分數。具有一致介面的站點或應用程式應該更容易實現,但在其他地方可能更難實現:

  • 除了最簡單的站點外,構建工具對於所有站點都是必不可少的。
  • 每個裝置上的“摺疊”都不同。
  • 站點可以有各種各樣的佈局,需要不同的關鍵CSS。
  • 關鍵的CSS工具可以與特定的框架、HTML生成的客戶端和動態內容進行鬥爭。
  • 這種技術主要有利於第一頁的載入。CSS被快取用於後續頁面,因此附加的內聯樣式將增加頁面的權重。

使用媒體查詢渲染

單個連線和縮小將使大多數站點受益,但需要大量較大螢幕樣式的站點可以拆分CSS檔案並使用媒體查詢載入:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!-- core styles loaded on all devices -->
<link rel="stylesheet" href="core.css">
<!-- served to screens at least 40em wide -->
<link rel="stylesheet" media="(min-width: 40em)" href="40em.css">
<!-- served to screens at least 80em wide -->
<link rel="stylesheet" media="(min-width: 80em)" href="80em.css">
<!-- core styles loaded on all devices --> <link rel="stylesheet" href="core.css"> <!-- served to screens at least 40em wide --> <link rel="stylesheet" media="(min-width: 40em)" href="40em.css"> <!-- served to screens at least 80em wide --> <link rel="stylesheet" media="(min-width: 80em)" href="80em.css">
<!-- core styles loaded on all devices -->
<link rel="stylesheet" href="core.css">
<!-- served to screens at least 40em wide -->
<link rel="stylesheet" media="(min-width: 40em)" href="40em.css">
<!-- served to screens at least 80em wide -->
<link rel="stylesheet" media="(min-width: 80em)" href="80em.css">

本例假定採用移動優先的方法。移動裝置載入core.css,但可能不需要下載或解析其餘的樣式表。

使用漸進式渲染

漸進式渲染是一種為單獨的頁面或元件定義單獨樣式表的技術。它可以使非常大的站點受益,在這些站點中,單個頁面由廣泛的元件構成。

在HTML中引用元件之前立即載入每個CSS檔案:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<head>
<!-- core styles -->
<link rel="stylesheet" href="core.css" />
</head>
<body>
<!-- header -->
<link rel="stylesheet" href="header.css" />
<header>...</header>
<!-- primary content -->
<link rel="stylesheet" href="main.css" />
<main>
<!-- widget styling -->
<link rel="stylesheet" href="widget.css" />
<div class="mywidget>...</div>
</main>
<!-- footer -->
<link rel="stylesheet" href="footer.css" />
<footer>...</footer>
</body>
<head> <!-- core styles --> <link rel="stylesheet" href="core.css" /> </head> <body> <!-- header --> <link rel="stylesheet" href="header.css" /> <header>...</header> <!-- primary content --> <link rel="stylesheet" href="main.css" /> <main> <!-- widget styling --> <link rel="stylesheet" href="widget.css" /> <div class="mywidget>...</div> </main> <!-- footer --> <link rel="stylesheet" href="footer.css" /> <footer>...</footer> </body>
<head>
  <!-- core styles -->
  <link rel="stylesheet" href="core.css" />
</head>
<body>
  <!-- header -->
  <link rel="stylesheet" href="header.css" />
  <header>...</header>
  <!-- primary content -->
  <link rel="stylesheet" href="main.css" />
  <main>
    <!-- widget styling -->
    <link rel="stylesheet" href="widget.css" />
    <div class="mywidget>...</div>
  </main>
  <!-- footer -->
  <link rel="stylesheet" href="footer.css" />
  <footer>...</footer>
</body>

這在大多數瀏覽器中行之有效。(Safari顯示一個空白頁面,直到載入所有CSS,但它不應該明顯比單個大樣式表差。)

採用Web元件還鼓勵使用在呈現自定義元素時載入的範圍樣式。

優化CSS效能

CSS技術和屬性給瀏覽器、CPU、記憶體、頻寬和其他資源帶來了不同的壓力。以下提示可以幫助您避免不必要的處理和緩慢的效能。

採用現代佈局技術(Grid和Flexbox)

基於浮動的佈局很難建立,使用大量屬性,需要連續調整邊距和填充,必須使用媒體查詢進行管理,並且需要大量的瀏覽器處理。多年來,它們是唯一可行的佈局方法,但已不再必要。使用以下任一選項:

  • CSS Flexbox用於一維佈局,可以換行到下一行。它是選單、影象庫、卡片等的理想選擇。
  • CSS Grid用於具有顯式行和列的二維佈局。它非常適合頁面佈局。

兩者都更易於開發,使用更少的程式碼,渲染速度更快,並且無需媒體查詢即可適應任何螢幕大小。

非常舊的瀏覽器無法識別現代的flexbox和網格屬性,因此每個元素都成為一個塊。以簡單的移動式線性佈局顯示它們:不需要使用基於浮點的回退來模擬設計。

用CSS漸變和效果替換影象

在可能的情況下,選擇CSS程式碼而不是影象。使用漸變、邊界、半徑、陰影、過濾器、混合模式、遮罩、剪裁和偽元素效果進行實驗,以重用或替換現有影象。

CSS效果使用更少的頻寬,更容易修改,並且通常可以設定動畫。

避免過度使用高成本的屬性

您可能有簡潔的宣告性程式碼,但某些CSS需要比其他CSS更多的處理。以下屬性觸發繪畫計算,當過度使用時計算成本可能會很高:

  • position: fixed
  • border-radius
  • box-shadow
  • text-shadow
  • opacity
  • transform
  • filter
  • backdrop-filter
  • background-blend-mode

儘可能使用CSS過渡和動畫

CSS過渡和動畫總是比JavaScript支援的效果更平滑,後者修改類似的屬性。它們不會在非常舊的瀏覽器中處理,但是,由於這些瀏覽器可能執行在效能較差的裝置上,這是最好的。

但是,請避免過多的動畫。這些效果應該能夠增強使用者體驗,而不會對效能產生負面影響或導致暈車。檢查prefers-reduced-motion媒體查詢,必要時禁用動畫。

避免觸發重新佈局的動畫屬性

更改元素的尺寸(寬度、高度、填充、邊框)或位置(頂部、底部、左側、右側、邊距)可能會導致整個頁面在每個動畫幀上重新佈局。要設定動畫的最有效特性是:

  • opacity
  • filter: 模糊、對比度、陰影和其他效果
  • transform: 平移(移動)、縮放或旋轉圖元素

瀏覽器可以使用硬體加速的GPU在自己的層中渲染這些效果,因此隻影響合成階段。

如果必須設定其他屬性的動畫,可以通過使用position:absolute將元素從頁面流中移除來提高效能。

注意複雜選擇器

瀏覽器將快速解析最複雜的CSS選擇器,但簡化它們會減少檔案大小並提高效能。複雜選擇器通常是在CSS前處理器(如Sass)中建立深度巢狀的結構時生成的。

指示哪些元素將更改

CSS will-change屬性允許您警告元素將如何更改或設定動畫,以便瀏覽器可以提前進行優化:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
.myelement {
will-change: transform, opacity;
}
.myelement { will-change: transform, opacity; }
.myelement {
  will-change: transform, opacity;
}

可以定義任意數量的逗號分隔值,但該屬性只能作為解決已知效能問題的最後手段。您不應該將它應用於太多的元素,並確保給它足夠的時間進行初始化。

考慮CSS Containment

Containment是一種新的CSS特性,它允許您識別頁面的孤立子樹,從而提高效能。瀏覽器可以通過呈現(或不呈現)特定的DOM內容塊來優化處理。

contain屬性在空格分隔的列表中接受以下一個或多個值:

  • none: 未應用Containment
  • layout: 元素的佈局與頁面的其餘部分隔離-其內容不會影響其他元素
  • paint: 圖元的子圖元不會顯示在其邊界之外
  • size: 可以在不檢查子元素的情況下確定元素的大小-維度與內容無關

還提供了兩個特殊值:

  • strict: 應用所有containment 規則(無規則除外)
  • content: 應用佈局和繪製

重要:一個頁面有一個包含應用 contain: strict; 的 <ul> 列表;應用如果更改任何子項 <li> 的內容,瀏覽器將不會重新計算該項、列表中的其他項或頁面上任何其他元素的大小或位置。

大多數現代瀏覽器都支援CSS Containment。Safari或較舊的應用程式中不支援Containment,但在這些應用程式中可以安全地使用Containment,因為瀏覽器將忽略該屬性。

對“Save-Data”標頭作出響應

Save Data是一個HTTP請求頭,指示使用者已請求減少的資料。在某些瀏覽器中,它可能被標記為“Lite”或“Turbo”模式。

啟用後,每個瀏覽器請求都會傳送一個 Save-Data 標頭:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
GET /main.css HTTP/1.0
Host: site.com
Save-Data: on
GET /main.css HTTP/1.0 Host: site.com Save-Data: on
GET /main.css HTTP/1.0
Host: site.com
Save-Data: on

當檢測到Save-Data時,伺服器可以做出相應的響應。在CSS的情況下,它可以傳送一個簡單的移動式線性佈局,使用OS字型,切換到塊顏色,或者載入低解析度的影象背景。

注意:伺服器應在修改請求時返回以下標頭,以確保在使用者關閉Lite/Turbo模式時不會快取和重用最小內容:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Vary: Accept-Encoding, Save-Data
Vary: Accept-Encoding, Save-Data
Vary: Accept-Encoding, Save-Data

客戶端JavaScript也可以檢測到此標頭。當未啟用“Save-Data”時,以下程式碼將bestUX類新增到 <html> 元素:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
if ('connection' in navigator && !navigator.connection.saveData) {
document.documentElement.classList.add('bestUX');
}
if ('connection' in navigator && !navigator.connection.saveData) { document.documentElement.classList.add('bestUX'); }
if ('connection' in navigator && !navigator.connection.saveData) {
  document.documentElement.classList.add('bestUX');
}

然後,樣式表可以相應地做出響應,而無需任何伺服器操作:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/* no hero image by default */
header {
background-color: #abc;
background-image: none;
}
/* hero image when no Save-Data */
.bestUX header {
background-image: url("hero.jpg");
}
/* no hero image by default */ header { background-color: #abc; background-image: none; } /* hero image when no Save-Data */ .bestUX header { background-image: url("hero.jpg"); }
/* no hero image by default */
header {
  background-color: #abc;
  background-image: none;
}
/* hero image when no Save-Data */
.bestUX header {
  background-image: url("hero.jpg");
}

prefers-reduced-data媒體查詢提供了一個僅CSS選項作為替代,儘管在編寫本文時,任何瀏覽器都不支援此選項:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/* no hero image by default */
header {
background-color: #abc;
background-image: none;
}
/* hero image when no Save-Data */
@media (prefers-reduced-data: no-preference) {
header {
background-image: url("hero.jpg");
}
}
/* no hero image by default */ header { background-color: #abc; background-image: none; } /* hero image when no Save-Data */ @media (prefers-reduced-data: no-preference) { header { background-image: url("hero.jpg"); } }
/* no hero image by default */
header {
  background-color: #abc;
  background-image: none;
}
/* hero image when no Save-Data */
@media (prefers-reduced-data: no-preference) {
  header {
    background-image: url("hero.jpg");
  }
}

小結

對於CSS效能的優化有很多選擇,但是對於新專案,請考慮以下做法:

  • 使用移動優先的方法:首先編寫最簡單的移動佈局,然後隨著螢幕空間和瀏覽器功能集的增加新增增強功能。
  • 將CSS拆分為具有可識別責任的單獨檔案:CSS前處理器或CMS外掛可以將CSS部分合併到單個檔案中。
  • 新增一個構建步驟:提供了一些工具,可以自動刪除程式碼、識別問題、連線、縮小、減少影象大小等。自動化使生活更輕鬆,而且您不太可能忘記優化步驟。
  • 記錄樣式表:帶有文件化示例的樣式指南將使您的程式碼更易於獲取和維護。您將能夠識別和刪除舊的CSS,而無需付出任何代價。

最後,學習CSS!您知道的越多,需要編寫的程式碼就越少,Web應用程式就會變得越快。無論您使用哪種平臺和框架,它都將使您成為更好的開發人員。

評論留言