content-visibility:可提升算繪成效的全新 CSS 資源

略過轉譯畫面外內容,縮短初始載入時間。

Vladimir Levin
Vladimir Levin

在 Chromium 85 中推出的 content-visibility 屬性,可能是用來改善網頁載入效能的全新 CSS 屬性之一。content-visibility 可讓使用者代理程式在必要前,略過元素的轉譯工作 (包括版面配置和繪製工作)。由於系統會略過轉譯作業,因此如果大部分內容位於畫面外,使用 content-visibility 屬性可大幅加快初始使用者的載入速度。還能夠加快與螢幕內容的互動速度。完美結合。

以圖表呈現網路成效的示意圖
在我們的文章示範中,將 content-visibility: auto 套用至區塊內容區域,可在初始載入時提升 7 倍的轉譯效能。請繼續閱讀以瞭解詳情。

瀏覽器支援

瀏覽器支援

  • 85
  • 85
  • 124

資料來源

content-visibility 依賴 CSS 遏制規格中的基本項目。雖然目前只有 Chromium 85 支援 content-visibility (且在 Firefox 中被視為「值得設計原型」),但大多數新式瀏覽器都支援「遏制規格」。

CSS 遏制

CSS 遏制的主要目標,在於提供與網頁其他部分可預測的隔離元素隔離,進而改善網頁內容的轉譯效能。

基本上,開發人員可以告知瀏覽器會將網頁的哪些部分封裝成一組內容,讓瀏覽器瞭解內容,而不必考慮子樹狀結構外的狀態。如果知道哪些位元的內容 (子樹狀結構) 含有獨立內容,瀏覽器便可做出有關網頁轉譯的最佳化決策。

CSS 內含有四種類型,每個 contain CSS 屬性可能的值都可以合併成以空格分隔的值清單:

  • size:元素的大小限制可確保元素的方塊能順利顯示,而無須檢查其子系。這表示如果我們需要元素的大小,就可以略過子系的版面配置。
  • layout:版面配置包含表示子係不會影響頁面上其他方塊的外部版面配置。如此一來,如果我們只要進行其他方塊的版面配置,就可以略過子系的版面配置。
  • style:樣式包含可確保可能不只對子系效果的屬性 (例如計數器) 不會逸出元素。這樣一來,如果我們只要運算其他元素的樣式,就可能會略過子系的樣式運算作業。
  • paint:繪製限制可確保內含方塊的子係不會在邊界外顯示。沒有明顯可以溢出元素的情況,如果元素位於畫面外或因其他原因未顯示,您也無法顯示其子系。這樣一來,如果元素在畫面外,我們就可能略過子層繪製作業。

使用 content-visibility 略過算繪工作

瀏覽器最佳化作業只有在指定合適的組合時才會啟動,因此可能難以判斷要使用的包含值。您可以對值執行測試,看看何者成效最佳,也可以使用另一個名為 content-visibility 的 CSS 屬性,自動套用需要的元件。content-visibility 可確保瀏覽器以最高效能提升效能。身為開發人員,您只須花費太多心力。

內容瀏覽權限屬性接受多個值,但 auto 是可立即改善效能的值。含有 content-visibility: auto 的元素會取得 layoutstylepaint 的抑制。如果元素不在畫面內 (與使用者無關,也就是與子樹狀結構聚焦或所選元素無關的元素),也會獲得 size 隔離,且會停止繪製命中測試內容。

使用這項功能,簡單來說,如果元素在畫面外,系統就不會轉譯其子系。瀏覽器在判定元素大小時不會考量其內容,並停止元素。系統會略過大部分的轉譯作業,例如元素子樹狀結構的樣式和版面配置。

當元素接近可視區域時,瀏覽器就不會再新增 size 元件,並開始繪製及點擊元素內容。這樣就能及時完成算繪工作,供使用者查看。

無障礙注意事項

content-visibility: auto 的其中一項功能是,在文件物件模型中仍可使用畫面外的內容,因此無障礙功能樹狀結構 (與 visibility: hidden 不同)。也就是說,使用者不用等待網頁載入或犧牲轉譯效能,即可在網頁上搜尋及瀏覽內容。

然而,另一方面,具有 display: nonevisibility: hidden 等樣式功能的「地標」元素在螢幕外時也會出現在無障礙樹狀結構中,因為瀏覽器在進入可視區域後,才會顯示這些樣式。為避免這些項目顯示在無障礙樹狀結構中,請務必一併新增 aria-hidden="true"

範例:旅遊網誌

在這個範例中,我們是在右側設定旅遊網誌的基準,並使用 content-visibility: auto 套用至左側的多個區塊。結果顯示初次載入網頁的轉譯時間,從 232 毫秒30 毫秒

旅遊網誌通常包含一組故事和幾張相片,以及一些描述性文字。在一般瀏覽器中瀏覽至旅遊網誌時,運作方式如下:

  1. 系統會從網路下載網頁的某個部分,以及所有必要的資源。
  2. 瀏覽器樣式和配置頁面所有內容的位置,不會考量使用者是否能看到內容。
  3. 瀏覽器會返回步驟 1,直到所有網頁和資源下載完成為止。

在步驟 2 中,瀏覽器會處理所有內容,尋找可能有所變更的項目。系統會更新任何新元素的樣式和版面配置,以及可能因為更新而改變的元素。這是轉譯作業。這需要時間。

旅遊網誌的螢幕截圖。
旅遊網誌範例。請參閱 Codepen 示範

現在,請想想在網誌中的個別報導中加入 content-visibility: auto 後會發生什麼情況。一般迴圈相同:瀏覽器下載並顯示網頁區塊。但差別在於前者的工作量 是在步驟 2 中執行的工作量

有了內容瀏覽權限,系統就會為使用者目前顯示的所有內容 (位於畫面上的) 設定樣式並配置內容。不過,在處理完全畫面外的故事時,瀏覽器會略過轉譯工作,只設定元素方塊本身的樣式和版面配置。

載入這個頁面的效能,就好比包含全螢幕故事和畫面外每則報導的空白方塊一樣。這種做法的效能更好,而且預計載入成本可減少 50% 以上。在這個範例中,轉譯時間從 232 毫秒提升到 30 毫秒。效能提升為 7 倍

你需要採取哪些工作才能獲取這些好處?首先,我們會將內容分為幾個部分:

註解螢幕截圖:使用 CSS 類別將內容分割成多個區段。
套用 story 類別,將內容分割成幾個區段的範例,以便接收 content-visibility: auto。請參閱 Codepen 示範

接著,我們將下列樣式規則套用至各部分:

.story {
  content-visibility: auto;
  contain-intrinsic-size: 1000px; /* Explained in the next section. */
}

使用 contain-intrinsic-size 指定元素的自然大小

為發揮 content-visibility 的潛在優點,瀏覽器必須套用大小限制,確保內容算繪結果不會對元素大小造成任何影響。這表示該元素會以空白的形式呈現。如果元素在一般區塊版面配置中並未指定高度,則高度會是 0。

這可能不太理想,因為捲軸大小會移動,因此必須仰賴高度非零的報導。

幸好,CSS 提供了另一個屬性 contain-intrinsic-size,這個屬性可有效指定元素受大小遮蔽影響元素的自然大小。在範例中,我們將這個值設為 1000px,做為區段的高度和寬度的預估值。

這表示其版面配置就像是具有「內建尺寸」維度的單一子項,確保未尺寸的 div 仍然佔用空間。contain-intrinsic-size 可做為預留位置大小,取代轉譯內容。

在 Chromium 98 以上版本中,contain-intrinsic-size 新增了 auto 關鍵字。如果指定此選項,瀏覽器會記住上次算繪的大小 (如有),並使用該大小取代開發人員提供的預留位置大小。舉例來說,如果您指定 contain-intrinsic-size: auto 300px,元素一開始的每個維度都會採用 300px 內建函式大小,但元素的內容算繪後,會保留算繪的內建函式大小。系統也會記住後續的顯示大小變更。實際上,這表示如果您捲動已套用 content-visibility: auto 的元素,然後將該元素向外捲動,它會自動保留理想的寬度和高度,而不會還原為預留位置的大小。這項功能特別適合無限捲動器,因為現在可在使用者瀏覽頁面時,持續自動調整尺寸估計值。

使用「content-visibility: hidden」隱藏內容

如果您希望無論內容是否在畫面上都保持不顯示,並想利用快取轉譯狀態的優點,該怎麼做?輸入:content-visibility: hidden

content-visibility: hidden 屬性可讓您享有與螢幕外 content-visibility: auto 一樣的未轉譯內容及快取算繪狀態帶來的所有好處。不過,與 auto 不同,系統不會自動開始在螢幕上顯示轉譯內容。

這可讓您進一步控管、隱藏元素的內容,並在稍後快速取消隱藏元素。

與其他隱藏元素內容的常見方式進行比較:

  • display: none:隱藏元素並刪除其算繪狀態。也就是說,取消隱藏該元素的費用相當於呈現含有相同內容的新元素費用。
  • visibility: hidden:隱藏元素並保留其算繪狀態。這並不會真正從文件中移除元素,因為元素 (它也是子樹狀結構) 仍會佔用網頁上的幾何圖形空間,您仍然可以點選。即使隱藏狀態,也會在需要時更新算繪狀態。

另一方面,content-visibility: hidden 會隱藏元素,同時保留其算繪狀態,因此如果有任何需要進行的變更,只有在重新顯示元素時才會發生 (例如移除 content-visibility: hidden 屬性)。

content-visibility: hidden 的幾個絕佳用途,就是實作進階虛擬捲動器以及測量版面配置。也非常適合單頁應用程式 (SPA)。可以將閒置的應用程式檢視畫面留在 DOM 中,同時套用 content-visibility: hidden 以防止顯示畫面,同時維持其快取狀態。這樣檢視畫面就會在再次啟用時快速顯示。

對下一個顯示內容 (INP) 互動的影響

INP 是一種指標,可用來評估網頁是否能依據使用者輸入內容做出穩定回應。回應速度會受到主執行緒上任何過多工作 (包括轉譯工作) 的影響。

每當特定網頁上的轉譯工作減少,主執行緒就能更迅速地回應使用者輸入內容。這包括轉譯工作,並視情況使用 content-visiblity CSS 屬性減少算繪工作,尤其是在大部分轉譯和版面配置作業的啟動時。

減少轉譯工作會直接影響 INP。當使用者嘗試與使用 content-visibility 屬性的網頁互動時,正確延遲版面配置與轉譯畫面外元素,您就可以讓主執行緒對使用者可見的重要工作做出回應。在某些情況下,這種做法有助於改善網頁的 INP。

結論

content-visibility 和 CSS 遏制規格代表 CSS 檔案很快將帶來一些令人振奮的效能提升。如要進一步瞭解這些屬性,請參閱: