Chrome 52 中的 CSS 防護機制

Paul Lewis

TL;DR

新的 CSS Containment 屬性可讓開發人員限制瀏覽器的樣式、版面配置和繪製作業範圍。

CSS 包含性。之前:版面配置耗時 59.6 毫秒。之後:版面配置耗時 0.05 毫秒

它有幾個值,因此語法如下:

    contain: none | strict | content | [ size || layout || style || paint ]

這項功能已在 Chrome 52 以上版本和 Opera 40 以上版本中推出 (Firefox 也提供公開支援),歡迎試用並告訴我們使用情形!

contain 屬性

製作網頁應用程式或複雜網站時,限制樣式、版面配置和繪製效果,是重要的效能挑戰。通常,整個 DOM 都會視為運算工作的「範圍內」,這可能表示在網路應用程式中嘗試使用自給自足的「檢視畫面」可能會變得棘手:DOM 某部分的變更可能會影響其他部分,而且無法告知瀏覽器哪些項目應在或不應在範圍內。

舉例來說,假設 DOM 的部分內容如下所示:

    <section class="view">
      Home
    </section>

    <section class="view">
      About
    </section>

    <section class="view">
      Contact
    </section>

您可以將新元素附加至一個檢視畫面,這樣就能觸發樣式、版面配置和繪製:

    <section class="view">
      Home
    </section>

    <section class="view">
      About
      <div class="newly-added-element">Check me out!</div>
    </section>

    <section class="view">
      Contact
    </section>

不過,在這種情況下,整個 DOM 實際上都屬於範圍內,也就是說,無論樣式、版面配置和繪製計算是否已變更,都必須考量所有元素。DOM 越大,所需的運算工作就越多,也就是說,您很可能會讓應用程式無法回應使用者輸入內容。

好消息是,現代瀏覽器會自動限制樣式、版面配置和繪圖作業的範圍,因此您不必採取任何行動,就能加快速度。

不過,更棒的消息是,我們推出了新的 CSS 屬性,可將範圍控制權交給開發人員:Containment

CSS Containment 是新屬性,使用關鍵字 contain,支援四個值:

  • layout
  • paint
  • size
  • style

您可以透過這些值限制瀏覽器需要執行的轉譯工作量。讓我們進一步瞭解每個值。

版面配置 (contain: layout)

版面配置容器化功能可能是容器化功能的最大優點,與 contain: paint 一樣。

版面配置通常是文件範圍,因此會根據 DOM 的大小進行縮放,因此如果您變更元素的 left 屬性,可能就需要檢查 DOM 中的每個元素。

在此啟用容器功能,可能會將元素數量減少到只有少數幾個,而不是整份文件,這樣瀏覽器就不必執行大量不必要的工作,也能大幅提升效能。

繪製 (包含:繪製)

範圍設定是另一個非常實用的容器功能。繪圖封存功能本質上會裁剪問題元素,但也有一些其他副作用:

  • 它可做為絕對位置和固定位置元素的容器區塊。這表示任何子項都會根據具有 contain: paint 的元素定位,而非任何其他父項元素,例如文件。
  • 這會成為堆疊情境。這表示 z-index 之類的項目會對元素產生影響,而子項會根據新結構定義進行堆疊。
  • 成為新的格式設定內容。也就是說,如果您有包含繪圖容器的區塊層級元素,系統會將其視為新的獨立版面配置環境。也就是說,元素外部的版面配置通常不會影響包含元素的子項。

大小 (包含:大小)

contain: size 的意思是,元素的子項不會影響父項的大小,且系統會使用推斷或宣告的尺寸。因此,如果您設定 contain: size,但未指定元素的尺寸 (直接或透過 flex 屬性),系統會以 0 像素 x 0 像素的大小顯示元素!

大小限制功能其實是一種雙重保障措施,可確保您不會依賴子項元素來設定大小,但本身並不會帶來太多效能優勢。

樣式 (contain: style)

變更元素樣式對 DOM 樹狀結構的影響,很難預測會如何影響樹狀結構。舉例來說,如果您使用 CSS 計數器,在子項中變更計數器,可能會影響文件中其他地方使用相同名稱的計數器值。設定 contain: style 後,樣式變更不會傳遞至包含元素以外的元素。

為求明確,contain: style 不會提供您從 Shadow DOM 取得的範圍樣式;這裡的容器僅會限制樹狀結構中在樣式變異時要考量的部分,不會在宣告時限制。

嚴格和內容限制

您也可以結合 contain: layout paint 等關鍵字,只將這些行為套用至元素。但 contain 也支援兩個額外的值:

  • contain: strictcontain: size layout paint 的意思相同
  • contain: contentcontain: layout paint 的意思相同

如果您事先知道元素的大小 (或希望保留其尺寸),使用嚴格限制的容器會很實用。不過請注意,如果您在宣告嚴格限制的容器時不指定尺寸,由於系統會隱含大小限制,元素可能會顯示為 0 像素 x 0 像素的方塊。

另一方面,內容容器可大幅改善範圍,但您不必事先知道或指定元素的尺寸。

在兩者中,contain: content 是您應預設使用的選項。當 contain: content 無法滿足您的需求時,您應將嚴格限制視為一種備用方法。

請告訴我們使用狀況

容器是向瀏覽器指出您想在網頁中保留哪些內容的絕佳方法。請在 Chrome 52 以上版本中試用,並告訴我們使用體驗!