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

略過螢幕外內容的算繪作業,縮短初始載入時間。

Vladimir Levin
Vladimir Levin

發布日期:2020 年 8 月 5 日

content-visibility 屬性可讓使用者代理程式略過元素的轉譯工作,包括版面配置和繪畫工作,直到需要相關作業為止。由於系統會略過轉譯作業,因此如果大部分內容都在畫面外,使用 content-visibility 屬性可讓初始使用者載入作業變得更快速。也能讓使用者更快與畫面上的內容互動。很不錯。

瀏覽器支援

  • Chrome:85。
  • Edge:85。
  • Firefox:125。
  • Safari:18 歲。

資料來源

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

CSS 容器

CSS 容器的主要目標是透過可預測的 DOM 子樹隔離,讓網頁內容的轉譯效能提升。

基本上,開發人員可以告訴瀏覽器網頁上有哪些部分封裝為一組內容,讓瀏覽器可以瞭解內容,而不需要考慮子樹狀結構以外的狀態。瞭解哪些內容部分 (子樹狀結構) 包含獨立內容,讓瀏覽器能夠針對轉譯網頁做出最佳化決策。

CSS 容器有四種型別,每種型別都是 contain CSS 屬性的可能值,可在以空格分隔的值清單中合併:

  • size:元素的大小容納功能可確保元素的方塊能夠排版,而不需要檢查其子項。也就是說,如果我們只需要元素的大小,可以略過子項的版面配置。
  • layout:版面配置包含表示子係不會影響頁面上其他方塊的外部版面配置。這可讓我們可能略過子系的版面配置,但如果我們要只配置其他方塊,就可能會這麼做。
  • style:樣式封存可確保屬性不會逸出元素 (例如計數器),而這些屬性可能會對其子項以外的其他項目產生效果。這樣一來,如果我們只想計算其他元素的樣式,就可以略過子項的樣式運算。
  • paint:繪製封閉區域可確保包含方塊的子項不會顯示在其邊界之外。元素完全不會溢位,如果元素在畫面外或未顯示時,就不會顯示其子系。如此一來,當元素不在畫面外時,我們就可以略過子系繪製作業。

使用 content-visibility 略過轉譯工作

由於瀏覽器最佳化功能只有在指定適當的集合時才會啟動,因此您可能很難判斷要使用哪些容器值。您可以嘗試調整這些值,看看哪個值最適合,也可以使用 content-visibility 自動套用所需的限制。content-visibility 可確保您能以最少的開發人員作業量,獲得瀏覽器提供的最大效能增益。

content-visibility 屬性可接受多個值,但 auto 可立即改善效能。含有 content-visibility: auto 的元素會獲得 layoutstylepaint 容器。如果元素位於畫面外 (且與使用者無關的元素是子樹狀結構中具有焦點或已選取的項目),則也會取得 size 包含 (且會停止繪製hit-testing)。

使用這項功能,簡而言之,如果元素位於畫面外,系統就不會算繪其子項。瀏覽器會在不考慮任何內容的情況下決定元素大小,然後就停止運作。大部分的轉譯作業都會略過,例如元素子樹狀結構的樣式和版面配置。

當元素接近可視區域時,瀏覽器就不會再新增 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 類別將內容分割成多個部分的螢幕截圖註解。
為了接收 content-visibility: auto,將內容分割為多個區段的範例,並套用 story 類別。請參閱 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 會做為預留位置大小,取代算繪內容。

contain-intrinsic-sizeauto 關鍵字會讓瀏覽器記住上次算繪的大小 (如果有的話),並使用該大小,而非開發人員提供的預留位置大小。舉例來說,如果您指定 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 來避免顯示,但仍維持快取狀態。這樣一來,當檢視畫面再次啟用時,就能快速算繪。

對 Interaction to Next Paint (INP) 的影響

INP 是一種指標,用於評估網頁回應使用者輸入內容的可靠程度。主執行緒上執行的作業量過多 (包括轉譯作業),可能會影響回應速度。

只要您能減少任何網頁的轉譯工作,就能讓主執行緒更快回應使用者輸入內容。這包括算繪作業,在適當情況下使用 content-visiblity CSS 屬性可減少算繪作業,尤其是在啟動期間,因為大部分的算繪和版面配置作業都會在這個階段完成。

減少轉譯工作會對 INP 造成直接影響。當使用者嘗試與使用 content-visibility 屬性正確延遲版面配置和非螢幕元素轉譯作業的網頁互動時,您會讓主執行緒有機會回應使用者可見的重要工作。在某些情況下,這麼做可改善網頁的 INP。

結論

content-visibility 和 CSS Containment 規格,意味著 CSS 檔案的成效將獲得大幅提升。如要進一步瞭解這些屬性,請參閱: