作者 | 大漠

使用者在通路一個Web網站(頁面)或應用時,總是希望它的加載速度快,功能流暢。如果過于慢,使用者就很有可能失去耐心而離開你的Web網站或應用。作為開發人員,給自己應用提供更快的通路速度,提供很好的使用者體驗是必備的基礎技能,而且Web開發者在開發中也可以做很多事情來改善使用者體驗。那我們今天就來和大家聊聊,在CSS方面有哪些技巧可以幫助我們來提高Web頁面的渲染速度。
内容可見性(content-visibility)
一般來說,大多數Web應用都有複雜的UI元素,而且有的内容會在裝置可視區域之外(内容超出了使用者浏覽器可視區域),比如下圖中紅色區域就在手機裝置螢幕可視區域之外:
在這種場合下,我們可以使用CSS的
content-visibility
來跳過螢幕外的内容渲染。也就是說,如果你有大量的離屏内容(Off-screen Content),這将會大幅減少頁面渲染時間。
這個功能是CSS新增的特性,隸屬于 W3C 的 CSS Containment Module Level 2 子產品。也是對提高渲染性能影響最大的功能之一。
content-visibility
可以接受
visible
、
auto
和
hidden
三個屬性值,但我們可以在一個元素上使用
content-visibility:auto
來直接的提升頁面的渲染性能。
假設我們有一個像下面的頁面,整個頁面有個卡片清單,大約有
375
張,大約在螢幕可視區域能顯示
12
張卡片。正如下圖所示,渲染這個頁面浏覽器用時大約
1037ms
:
你可以給所有卡片添加
content-visibility
.card {
content-visibility: auto;
}
所有卡片加入
content-visibility
樣式之後,頁面的渲染時間下降到150ms,差不多提高了六倍的渲染性能:
正如你所看到的,
content-visibility
非常強大,提高頁面渲染非常有用。換然話說,有了CSS的
content-visibility
屬性,影響浏覽器的渲染過程就變得更加容易。本質上,這個屬性 改變了一個元素的可見性,并管理其渲染狀态。
content-visibility
有點類似于CSS的
display
visibility
屬性,然而,
content-visibility
的操作方式與這些屬性不同。
content-visibility
的關鍵能力是,它允許我們推遲我們選擇的HTML元素渲染。預設情況之下,浏覽器會渲染DOM樹内所有可以被使用者檢視的元素。使用者可以看到視窗可視區域中所有元素,并通過滾動檢視頁面内其他元素。一次渲染所有的元素(包括視窗可視區域之外不可見的HTML元素)可以讓浏覽器正确計算頁面的尺寸,同時保持整個頁面的布局和滾動條的一緻性。
如果浏覽器不渲染頁面内的一些元素,滾動将是一場噩夢,因為無法正确計算頁面高度。這是因為,
content-visibility
會将配置設定給它的元素的高度(
height
)視為
,浏覽器在渲染之前會将這個元素的高度變為
,進而使我們的頁面高度和滾動變得混亂。但如果已經為元素或其子元素顯式設定了高度,那這種行為就會被覆寫。如果你的元素中沒顯式設定高度,并且因為顯式設定
height
可能會帶來一定的副作用而沒設定,那麼我們可以使用
contain-intrinsic-size
來確定元素的正确渲染,同時也保留延遲渲染的好處。
.card {
content-visibility: auto;
contain-intrinsic-size: 200px;
}
這也意味着它将像有一個“固有尺寸”(Intrinsic-size)的單一子元素一樣布局,確定你沒設定尺寸的
div
(示例中的
.card
)仍然占據空間。
contain-intrinsic-size
作為一個占位符尺寸來替代渲染内容。
雖然
contain-intrinsic-size
能讓元素有一個占位空間,但如果有大量的元素都設定了
content-visibility: auto
,滾動條仍然會有較小的問題。
content-visibility
提供的另外兩個值
visible
hidden
可以讓我們實作像元素的顯式和隐藏,類似于
display
的
none
和非
none
值的切換:
在這種情況下,
content-visibility
可以提高頻繁顯示或隐藏的元素的渲染性能,例如模态框的顯示和隐藏。
`content-visibility可以提供這種性能提升,這要歸功于其隐藏值(
hidden`)的功能與其他值的不同:
-
:隐藏元素并破壞其渲染狀态。這意味着取消隐藏元素與渲染具有相同内容的新元素一樣昂貴display: none
-
:隐藏元素并保持其渲染狀态。這并不能真正從文檔中删除該元素,因為它(及其子樹)仍占據頁面上的幾何空間,并且仍然可以單擊。它也可以在需要時随時更新渲染狀态,即使隐藏也是如此visibility: hidden
-
:隐藏元素并保留其渲染狀态。這意味着該元素隐藏時行為和content-visibility: hidden
一樣,但再次顯示它的成本要低得多display: none
content-visibility
屬性的擴充閱讀:
-
: the new CSS property that boosts your rendering performancecontent-visibility
`-
https://web.dev/content-visibility/- More on
content-visibility
合理使用will-change
CSS渲染器(CSS Renderer)在渲染CSS樣式之前需要一個準備過程,因為有些CSS屬性需要CSS渲染器事先做很多準備才能實作渲染。這就很容易導緻頁面出現卡頓,給使用者帶來不好的體驗。
比如Web上的動效,通常情況之下,Web動畫(在動的元素)是和其他元素一起定期渲染的,以往在動畫開發時,會使用CSS的3D變換(
transform中的translate3d()
或
translateZ()
)來開啟GPU加速,讓動畫變得更流暢,但這樣做是一種黑魔法,會将元素和它的上下文提到另一個“層”,獨立于其他元素被渲染。可這種将元素提取到一個新層,相對來說代價也是昂貴的,這可能會使
transform
動畫延遲幾百毫秒。
不過,現在我可以不使用
transform
這樣的Hack手段來開啟GPU加速,可以直接使用CSS的
will-change
屬性,該屬性可以表明元素将修改特定的屬性,讓浏覽器事先進行必要的優化。也就是說,
will-change
是一個UA提示,它不會對你使用它的元素産生任何樣式上的影響。但值得注意的是,如果建立了新的層疊上下文,它可以産生外觀效果。
比如下面這樣的一個動畫示例:
<!-- HTML -->
<div class="animate"></div>
/* CSS */
.animate {
will-change: opacity
}
浏覽器渲染上面的代碼時,浏覽器将為該元素建立一個單獨的層。之後,它将該元素的渲染與其他優化一起委托給GPU,即,浏覽器會識别
will-change
屬性,并優化未來與不透明相關的變化。這将使動畫變得更加流暢,因為GPU加速接管了動畫的渲染。
根據 @Maximillian Laumeister 所做的性能基準,可以看到,他通過這種單行變化獲得了超過的渲染速度,和最初的渲染速度(大約
120FPS
)相比,提高
50FPS
左右。
70FPS
will-change
的使用并不複雜,它能接受的值有:
-
:預設值,浏覽器會根據具體情況,自行進行優化auto
-
:表示開發者将要改變元素的滾動位置,比如浏覽器通常僅渲染可滾動元素“滾動視窗”中的内容。而某些内容超過該視窗(不在浏覽器的可視區域内)。如果scroll-position
顯式設定了該值,将擴充渲染“滾動視窗”周圍的内容,進而順利地進行更長,更快的滾動(讓元素的滾動更流暢)will-change
-
:表示開發者将要改變元素的内容,比如浏覽器常将大部分不經常改變的元素緩存下來。但如果一個元素的内容不斷發生改變,那麼産生和維護這個緩存就是在浪費時間。如果content
顯式設定了該值,可以減少浏覽器對元素的緩存,或者完全避免緩存。變為從始至終都重新渲染元素。使用該值時需要盡量在文檔樹最末尾上使用,因為該值會被應用到它所聲明元素的子節點,要是在文檔樹較高的節點上使用的話,可能會對頁面性能造成較大的影響will-change
-
:表示開發者将要改變的元素屬性。如果給定的值是縮寫,則預設被擴充全,比如,<custom-ident>
設定的值是will-change
,那麼會補全所有padding
的屬性,如padding
;will-change: padding-top, padding-right, padding-bottom, padding-left
詳細的使用,請參閱:
- CSS Will Change Module Level 1
- Everything You Need to Know About the CSS
Propertywill-change
- CSS Reference:
will-change
雖然說
will-change
能提高性能,但這個屬性應該被認為是最後的手段,它不是為了過早的優化。隻有消退你必須處理性能問題時,你才應該使用它。如果你濫用的話,反而會降低Web的性能。比如:
使用 will-change
表示該元素在未來會發生變化。
是以,如果你試圖将
will-change
和動畫同時使用,它将不會給你帶來優化。是以,建議在父元素上使用
will-change
,在子元素上使用動畫。
.animate-element-parent {
will-change: opacity;
}
.animate-element {
transition: opacity .2s linear
}
不要使用非動畫元素。
當你在一個元素上使用
will-change
時,浏覽器會嘗試通過将元素移動到一個新的圖層并将轉換工作互動GPU來優化它。如果你沒有任何要轉換的内容,則會導緻資源浪費。
除此之外,要用好
will-change
也不是件易事,MDN在這方面做出了相應的描述:
- 不要将
應用到太多元素上:浏覽器已經盡力嘗試去優化一切可以優化的東西了。有一些更強力的優化,如果與will-change
結合在一起的話,有可能會消耗很多機器資源,如果過度使用的話,可能導緻頁面響應緩慢或者消耗非常多的資源。比如will-change
*{will-change: transform, opacity;}
- 有節制地使用:通常,當元素恢複到初始狀态時,浏覽器會丢棄掉之前做的優化工作。但是如果直接在樣式表中顯式聲明了
屬性,則表示目标元素可能會經常變化,浏覽器會将優化工作儲存得比之前更久。是以最佳實踐是當元素變化之前和之後通過腳本來切換will-change
的值will-change
- 不要過早應用
優化:如果你的頁面在性能方面沒什麼問題,則不要添加will-change
屬性來榨取一丁點的速度。will-change
的設計初衷是作為最後的優化手段,用來嘗試解決現有的性能問題。它不應該被用來預防性能問題。過度使用will-change
會導緻大量的記憶體占用,并會導緻更複雜的渲染過程,因為浏覽器會試圖準備可能存在的變化過程。這會導緻更嚴重的性能問題。will-change
- 給它足夠的工作時間:這個屬性是用來讓頁面開發者告知浏覽器哪些屬性可能會變化的。然後浏覽器可以選擇在變化發生前提前去做一些優化工作。是以給浏覽器一點時間去真正做這些優化工作是非常重要的。使用時需要嘗試去找到一些方法提前一定時間獲知元素可能發生的變化,然後為它加上
屬性。will-change
最後需要注意的是,建議在完成所有動畫後,将元素的
will-change
删除。下面這個示例展示如何使用腳本正确地應用
will-change
屬性的示例,在大部分的場景中,你都應該這樣做。
var el = document.getElementById('element');
// 當滑鼠移動到該元素上時給該元素設定 will-change 屬性
el.addEventListener('mouseenter', hintBrowser);
// 當 CSS 動畫結束後清除 will-change 屬性
el.addEventListener('animationEnd', removeHint);
function hintBrowser() {
// 填寫上那些你知道的,會在 CSS 動畫中發生改變的 CSS 屬性名們
this.style.willChange = 'transform, opacity';
}
function removeHint() {
this.style.willChange = 'auto';
}
在實際使用
will-change
可以記作以下幾個規則,即 五可做,三不可做:
- 在樣式表中少用
will-change
- 給
足夠的時間令其發揮該有的作用will-change
-
來針對超特定的變化(如,<custom-ident>
,left
等)opacity
- 如果需要的話,可以
中使用它(添加和删除)JavaScript
- 修改完成後,删除
will-change
- 不要同時聲明太多的屬性
- 不要應用在太多元素上
- 不要把資源浪費在已停止變化的元素上
讓元素及其内容盡可能獨立于文檔樹的其餘部分(contain)
W3C的CSS Containment Module Level 2除了提供前面介紹的
content-visibility
屬性之外,還有另一個屬性
contain
。該屬性允許我們指定特定的DOM元素和它的子元素,讓它們能夠獨立于整個DOM樹結構之外。目的是能夠讓浏覽器有能力隻對部分元素進行重繪、重排,而不必每次針對整個頁面。即,允許浏覽器針對DOM的有限區域而不是整個頁面重新計算布局,樣式,繪畫,大小或它們的任意組合。
在實際使用的時候,我們可以通過
contain
設定下面五個值中的某一個來規定元素以何種方式獨立于文檔樹:
-
:該值表示元素的内部布局不受外部的任何影響,同時該元素以及其内容也不會影響以上級layout
-
:該值表示元素的子級不能在該元素的範圍外顯示,該元素不會有任何内容溢出(或者即使溢出了,也不會被顯示)paint
-
:該值表示元素盒子的大小是獨立于其内容,也就是說在計算該元素盒子大小的時候是會忽略其子元素size
-
:該值是content
的簡寫contain: layout paint
-
strict
contain: layout paint size
在上述這幾個值中,
size
layout
paint
可以單獨使用,也可以互相組合使用;另外
content
strict
是組合值,即
content
是
layout paint
的組合,
strict
layout paint size
的組合。
contain
size
layout
paint
提供了不同的方式來影響浏覽器渲染計算:
-
:告訴浏覽器,當其内容發生變化時,該容器不應導緻頁面上的位置移動size
-
:告訴浏覽器,容器的後代不應該導緻其容器外元素的布局改變,反之亦然layout
-
:告訴浏覽器,容器的内容将永遠不會繪制超出容器的尺寸,如果容器是模糊的,那麼就根本不會繪制内容paint
@Manuel Rego Casasnovas提供了一個示例,向大家闡述和示範了
contain
是如何提高Web頁面渲染性能。這個示例中,有
10000
個像下面這樣的DOM元素:
<div class="item">
<div>Lorem ipsum...</div>
</div>
使用JavaScript的
textContent
這個API來動态更改
div.item > div
的内容:
const NUM_ITEMS = 10000;
const NUM_REPETITIONS = 10;
function log(text) {
let log = document.getElementById("log");
log.textContent += text;
}
function changeTargetContent() {
log("Change \"targetInner\" content...");
// Force layout.
document.body.offsetLeft;
let start = window.performance.now();
let targetInner = document.getElementById("targetInner");
targetInner.textContent = targetInner.textContent == "Hello World!" ? "BYE" : "Hello World!";
// Force layout.
document.body.offsetLeft;
let end = window.performance.now();
let time = window.performance.now() - start;
log(" Time (ms): " + time + "\n");
return time;
}
function setup() {
for (let i = 0; i < NUM_ITEMS; i++) {
let item = document.createElement("div");
item.classList.add("item");
let inner = document.createElement("div");
inner.style.backgroundColor = "#" + Math.random().toString(16).slice(-6);
inner.textContent = "Lorem ipsum...";
item.appendChild(inner);
wrapper.appendChild(item);
}
}
如果不使用
contain
,即使更改是在單個元素上,浏覽器在布局上的渲染也會花費大量的時間,因為它會周遊整個DOM樹(在本例中,DOM樹很大,因為它有
10000
個DOM元素):
在本例中,
div
的大小是固定的,我們在内部
div
中更改的内容不會溢出它。是以,我們可以将
contain: strict
應用到項目上,這樣當項目内部發生變化時,浏覽器就不需要通路其他節點,它可以停止檢查該元素上的内容,并避免到外部去。
盡管這個例子中的每一項都很簡單,但通過使用
contain
,Web性能得到很大的改變,從
~4ms
降到了
~0.04ms
,這是一個巨大的差異。想象一下,如果DOM樹具有非常複雜的結構和内容,但隻修改了頁面的一小部分,如果可以将其與頁面的其他部分隔離開來,那麼将會發生什麼情況呢?
有關于
contain
的更多内容:
- Let’s Take a Deep Dive Into the CSS Contain Property
- Helping Browsers Optimize With The CSS Contain Property
- CSS
contain
使用font-display解決由于字型造成的布局偏移(FOUT)
在Web開發的過程中,難免會使用
@font-face
技術引用一些特殊字型(系統沒有的字型),同時也可能會配合變量字型特性,使用更具個性化的字型。
@font-face
加載字型政策大概如下圖所示:
上圖來自于@zachleat的《A COMPREHENSIVE GUIDE TO FONT LOADING STRATEGIES》一文。
Web中使用非系統字型(
@font-face
規則引入的字型)時,浏覽器可能沒有及時得到Web字型,就會讓它用後備系統字型渲染,然後優化我們的字型。這個時候很容易引起未編排(Unstyled)的文本引起閃爍,整個排版本布局也看上去會偏移一下(FOUT)。
幸運的是,根據
@font-face
規則,
font-display
屬性定義了浏覽器如何加載和顯示字型檔案,允許文本在字型加載或加載失敗時顯示回退字型。可以通過依靠折中無樣式文本閃現使文本可見替代白屏來提高性能。
CSS的
font-display
屬性有五個不同的值:
-
:預設值。典型的浏覽器字型加載的行為會發生,也就是使用自定義字型的文本會先被隐藏,直到字型加載結束才會顯示。即字型展示政策與浏覽器一緻,目前,大多數浏覽器的預設政策類似auto
block
-
:給予字型一個較短的阻塞時間(大多數情況下推薦使用block
)和無限大的交換時間。換言之,如果字型未加載完成,浏覽器将首先繪制“隐形”文本;一旦字型加載完成,立即切換字型。為此,浏覽器将建立一個匿名字型,其類型與所選字型相似,但所有字形都不含“墨水”。使用特定字型渲染文本之後頁面方才可用,隻有這種情況下才應該使用3s
。block
-
:使用swap
,則阻塞階段時間為 ,交換階段時間無限大。也就是說,如果字型沒有完成加載,浏覽器會立即繪制文字,一旦字型加載成功,立即切換字型。與swap
類似,如果使用特定字型渲染文本對頁面很重要,且使用其他字型渲染仍将顯示正确的資訊,才應使用block
swap
-
:這個可以說是fallback
auto
的一種折中方式。需要使用自定義字型渲染的文本會在較短的時間不可見,如果自定義字型還沒有加載結束,那麼就先加載無樣式的文本。一旦自定義字型加載結束,那麼文本就會被正确賦予樣式。使用swap
時,阻塞階段時間将非常小(多數情況下推薦小于fallback
),交換階段也比較短(多數情況下建議使用100ms
)。換言之,如果字型沒有加載,則首先會使用後備字型渲染。一旦加載成功,就會切換字型。但如果等待時間過久,則頁面将一直使用後備字型。如果希望使用者盡快開始閱讀,而且不因新字型的載入導緻文本樣式發生變動而幹擾使用者體驗,3s
是一個很好的選擇。fallback
-
:效果和optional
幾乎一樣,都是先在極短的時間内文本不可見,然後再加載無樣式的文本。不過fallback
選項可以讓浏覽器自由決定是否使用自定義字型,而這個決定很大程度上取決于浏覽器的連接配接速度。如果速度很慢,那你的自定義字型可能就不會被使用。使用optional
時,阻塞階段時間會非常小(多數情況下建議低于optional
),交換階段時間為100ms
下面是使用
swap
值的一個例子:
@font-face {
font-family: "Open Sans Regular";
font-weight: 400;
font-style: normal;
src: url("fonts/OpenSans-Regular-BasicLatin.woff2") format("woff2");
font-display: swap;
}
在這個例子裡我們通過隻使用WOFF2檔案來縮寫字型。另外我們使用了
swap
作為
font-display
的值,頁面的加載情況将如下圖所示:
注意,一般放在
font-display
規則中使用。
@font-face
有關于字型加載和
font-display
更多的介紹,可以閱讀:
- A deep dive into webfonts
- How to avoid layout shifts caused by web fonts
- The Best Font Loading Strategies and How to Execute Them
- A font-display setting for slow connections
- How to Load Fonts in a Way That Fights FOUT and Makes Lighthouse Happy
- The importance of @font-face source order when used with preload
- The Fastest Google Fonts
- A COMPREHENSIVE GUIDE TO FONT LOADING STRATEGIES
scroll-behavior讓滾動更流暢
早前在滾動的特性和改變使用者體驗的滾動新特性中向大家介紹了幾個可以用來改變使用者體驗的滾動特性,比如滾動捕捉、
overscroll-behavior
scroll-behavior
scroll-behavior
是CSSOM View Module提供的一個新特性,可以輕易的幫助我們實作絲滑般的滾動效果。該屬性可以為一個卷軸欄指定滾動行為,其他任何的滾動,例如那些由于使用者行為而産生的滾動,不受這個屬性的影響。
scroll-behavior
接受兩個值:
-
:卷軸欄立即滾動auto
-
:卷軸欄通過一個使用者代理定義的時間段使用定義的時間函數來實作平穩的滾動,使用者代理平台應遵循約定,如果有的話smooth
除此之外,其還有三個全局的值:
inherit
initial
unset
使用起來很簡單,隻需要這個元素上使用
scroll-behavior:smooth
。是以,很多時候為了讓頁面滾動更平滑,建議在html中直接這樣設定一個樣式:
html {
scroll-behavior:smooth;
}
口說無憑,來看個效果對比,你會有更好的感覺:
scroll-behavior
屬性更多的介紹可以再花點時間閱讀下面這些文章:
- CSSOM View Module:scroll-behavior
- CSS-Tricks: scroll-behavior
- Native Smooth Scroll behavior
- PAGE SCROLLING IN VANILLA JAVASCRIPT
- smooth scroll behavior polyfill
開啟GPU渲染動畫
浏覽器針對處理CSS動畫和不會很好地觸發重排(是以也導緻繪)的動畫屬性進行了優化。為了提高性能,可以将被動畫化的節點從主線程移到GPU上。将導緻合成的屬性包括 3D transforms (
transform: translateZ()
rotate3d()
,等),
animating
,
transform
opacity
position: fixed
will-change
,和
filter
。一些元素,例如
<video>
<canvas>
<iframe>
,也位于各自的圖層上。将元素提升為圖層(也稱為合成)時,動畫轉換屬性将在GPU中完成,進而改善性能,尤其是在移動裝置上。
減少渲染阻止時間
今天,許多Web應用必須滿足多種形式的需求,包括PC、平闆電腦和手機等。為了完成這種響應式的特性,我們必須根據媒體尺寸編寫新的樣式。當涉及頁面渲染時,它無法啟動渲染階段,直到 CSS對象模型(CSSOM)已準備就緒。根據你的Web應用,你可能會有一個大的樣式表來滿足所有裝置的形式因素。
但是,假設我們根據表單因素将其拆分為多個樣式表。在這種情況下,我們可以隻讓主CSS檔案阻塞關鍵路徑,并以高優先級下載下傳它,而讓其他樣式表以低優先級方式下載下傳。
<link rel="stylesheet" href="styles.css">
将其分解為多個樣式表後:
<!-- style.css contains only the minimal styles needed for the page rendering -->
<link rel="stylesheet" href="styles.css" media="all" />
<!-- Following stylesheets have only the styles necessary for the form factor -->
<link rel="stylesheet" href="sm.css" media="(min-width: 20em)" />
<link rel="stylesheet" href="md.css" media="(min-width: 64em)" />
<link rel="stylesheet" href="lg.css" media="(min-width: 90em)" />
<link rel="stylesheet" href="ex.css" media="(min-width: 120em)" />
<link rel="stylesheet" href="print.css" media="print" />
預設情況下,浏覽器假設每個指定的樣式表都是阻塞渲染的。通過添加
media
屬性附加媒體查詢,告訴浏覽器何時應用樣式表。當浏覽器看到一個它知道隻會用于特定場景的樣式表時,它仍會下載下傳樣式,但不會阻塞渲染。通過将 CSS 分成多個檔案,主要的 阻塞渲染 檔案(本例中為
styles.css
)的大小變得更小,進而減少了渲染被阻塞的時間。
避免@import包含多個樣式表
通過
@import
,我們可以在另一個樣式表中包含一個樣式表。當我們在處理一個大型項目時,使用
@import
可以使代碼更加簡潔。
關于
@import
的關鍵事實是,它是一個阻塞調用,因為它必須通過網絡請求來擷取檔案,解析檔案,并将其包含在樣式表中。如果我們在樣式表中嵌套了
@import
,就會妨礙渲染性能。
/* style.css */
@import url("windows.css");
/* windows.css */
@import url("componenets.css");
與使用
@import
相比,我們可以通過多個
link
來實作同樣的功能,但性能要好得多,因為它允許我們并行加載樣式表。
注意動态修改自定義屬性方式
CSS自定義屬性又名CSS變量,該特性已經是非常成熟的特性了,可以在Web的開發中大膽的使用該特性:
:root { --color: red; }
button {
color: var(--color);
}
義屬性是個全局的自定義屬性(全局變量),可以被所有嵌套的子元素繼承。就上例而言,
--color
屬性允許任何
button
樣式将其作為變量使用。
熟悉CSS自定義屬性的同學都知道,可以使用
style.setProperty
來重新設定已注冊好的自定義屬性的值。但在修改根自定義屬性時,需要注意,因為它會影響Web的性能。早在2017年@Lisi Linhart 在《 Performance of CSS Variables》中闡述過。
- 在使用CSS變量時,我們總是要注意我們的變量是在哪個範圍内定義的,如果改變它,将影響許多子代,進而産生大量的樣式重新計算。
- 結合CSS變量使用
是一個很好的方法,可以獲得更多的靈活性,限制我們需要定義的變量數量。在不同的浏覽器中測試calc()
與CSS變量的結合,并沒有發現任何大的性能問題。然而在一些浏覽器中對一些機關的支援還是有限的,比如calc()
deg
,是以我們必須記住這一點。ms
- 如果我們比較一下在JavaScript中通過内聯樣式設定變量與
方法的性能标志,浏覽器之間有一些明顯的差異。在Safari中通過内聯樣式設定屬性的速度非常快,而在Firefox中則非常慢,是以使用setProperty
設定變量是首選setProperty
有關于這方面的具體細節就不在這闡述了,如果你對這方面感興趣的話,可以閱讀下面這幾篇文章:
- Performance of CSS Variables
- Control CSS loading with custom properties
- CSS Custom Properties performance in 2018
- Improving CSS Custom Properties performance
小結
可能很多人會說,5G已到來,終端裝置性能越來越好,網絡環境也越來越強,Web性能已不是問題了,但事實上在Web開發過程中總是難免碰到性能是的問題。而且我們為使用者提供更流暢的體驗也是我們必備技術之一。時至今日,優化Web性能的方式和手段很多,但在開發時注重每個細節,可以讓我們把性能做得更好。正如文章中提到這些。
除了文章提到的這幾個點,還有一些其他的方法可以使用CSS來提高網頁的性能。當然,文章中提到的一些特性還沒有得到所有浏覽器支援,比如
content-visibility
contain
等,但在未來它們肯定能讓頁面渲染帶來更快的渲染。另外,文章中提到的一些技巧并沒有深入闡述,比如CSS的引用方式,CSS的阻塞等。如果你對這方面感興趣的話,可以繼續觀注後續的相關更新;如果你在這方面更好的建議或經驗,歡迎與我們分享。