本篇內(nèi)容介紹了“怎么使用content-visibility屬性優(yōu)化渲染性能”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
遵化網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),遵化網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為遵化上千多家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)營銷網(wǎng)站建設(shè)要多少錢,請找那個售后服務(wù)好的遵化做網(wǎng)站的公司定做!
content-visibility
?content-visibility
:屬性控制一個元素是否渲染其內(nèi)容,它允許用戶代理(瀏覽器)潛在地省略大量布局和渲染工作,直到需要它為止。
MDN 原文:The content-visibility CSS property controls whether or not an element renders its contents at all, along with forcing a strong set of containments, allowing user agents to potentially omit large swathes of layout and rendering work until it becomes needed. Basically it enables the user agent to skip an element's rendering work (including layout and painting) until it is needed — which makes the initial page load much faster.
它有幾個常見的取值。
/* Keyword values */ content-visibility: visible; content-visibility: hidden; content-visibility: auto;
分別解釋一下:
content-visibility: visible
:默認(rèn)值,沒有任何效果,相當(dāng)于沒有添加 content-visibility
,元素的渲染與往常一致。
content-visibility: hidden
:與 display: none
類似,用戶代理將跳過其內(nèi)容的渲染。(這里需要注意的是,跳過的是內(nèi)容的渲染)
content-visibility: auto
:如果該元素不在屏幕上,并且與用戶無關(guān),則不會渲染其后代元素。
當(dāng)然,除 content-visibility
之外,還有一個與之配套的屬性 -- contain-intrinsic-size
。
contain-intrinsic-size
:控制由 content-visibility
指定的元素的自然大小。
上面兩個屬性光看定義和介紹會有點(diǎn)繞。
我們首先來看看 content-visibility
如何具體使用。
content-visibility: visible
是默認(rèn)值,添加后沒有任何效果,我們就直接跳過。
content-visibility: hidden
優(yōu)化展示切換性能首先來看看 content-visibility: hidden
,它通常會拿來和 display: none
做比較,但是其實(shí)它們之間還是有很大的不同的。
首先,假設(shè)我們有兩個 DIV 包裹框:
11112222
設(shè)置兩個 div 為 200x200
的黑色塊:
.g-wrap > div { width: 200px; height: 200px; background: #000; }
效果如下:
OK,沒有問題,接下來,我們給其中的 .hidden
設(shè)置 content-visibility: hidden
,看看會發(fā)生什么:
.hidden { content-visibility: hidden; }
效果如下:
注意,仔細(xì)看效果,這里添加了 content-visibility: hidden
之后,消失的只是添加了該元素的 div 的子元素消失不見,而父元素本身及其樣式,還是存在頁面上的。
如果我們?nèi)サ粼O(shè)置了 content-visibility: hidden
的元素本身的 width
、height
、padding
、margin
等屬性,則元素看上去就如同設(shè)置了 display: none
一般,在頁面上消失不見了。
那么,content-visibility: hidden
的作用是什么呢?
設(shè)置了 content-visibility: hidden
的元素,其元素的子元素將被隱藏,但是,它的渲染狀態(tài)將會被緩存。所以,當(dāng) content-visibility: hidden
被移除時,用戶代理無需重頭開始渲染它和它的子元素。
因此,如果我們將這個屬性應(yīng)用在一些一開始需要被隱藏,但是其后在頁面的某一時刻需要被渲染,或者是一些需要被頻繁切換顯示、隱藏狀態(tài)的元素上,其渲染效率將會有一個非常大的提升。
content-visibility: auto
實(shí)現(xiàn)虛擬列表OK,接下來是 content-visibility
的核心用法,利用 auto
屬性值。
content-visibility: auto
的作用是,如果該元素不在屏幕上,并且與用戶無關(guān),則不會渲染其后代元素。是不是與 LazyLoad 非常類似?
我們來看這樣一個 DEMO ,了解其作用:
假設(shè),我們存在這樣一個 HTML 結(jié)構(gòu),含有大量的文本內(nèi)容:
...// ... 包含了 N 個 paragraph...
每個 .paragraph
的內(nèi)容如下:
因此,整個的頁面看起來就是這樣的:
由于,我們沒有對頁面內(nèi)容進(jìn)行任何處理,因此,所有的 .paragraph
在頁面刷新的一瞬間,都會進(jìn)行渲染,看到的效果就如上所示。
當(dāng)然,現(xiàn)代瀏覽器愈加趨于智能,基于這種場景,其實(shí)我們非常希望對于仍未看到,仍舊未滾動到的區(qū)域,可以延遲加載,只有到我們需要展示、滾動到該處時,頁面內(nèi)容才進(jìn)行渲染。
基于這種場景,content-visibility: auto
就應(yīng)運(yùn)而生了,它允許瀏覽器對于設(shè)置了該屬性的元素進(jìn)行判斷,如果該元素當(dāng)前不處于視口內(nèi),則不渲染該元素。
我們基于上述的代碼,只需要最小化,添加這樣一段代碼:
.paragraph { content-visibility: auto; }
再看看效果,仔細(xì)觀察右側(cè)的滾動條:
這里我使用了
::-webkit-scrollbar
相關(guān)樣式,讓滾動條更明顯。
可能你還沒意識到發(fā)生了什么,我們對比下添加了 content-visibility: auto
和沒有添加 content-visibility: auto
的兩種效果下文本的整體高度:
有著非常明顯的差異,這是因?yàn)?,設(shè)置了 content-visibility: auto
的元素,在非可視區(qū)域內(nèi),目前并沒有被渲染,因此,右側(cè)內(nèi)容的高度其實(shí)是比正常狀態(tài)下少了一大截的。
好,我們實(shí)際開始進(jìn)行滾動,看看會發(fā)生什么:
由于下方的元素在滾動的過程中,出現(xiàn)在視口范圍內(nèi)才被渲染,因此,滾動條出現(xiàn)了明顯的飄忽不定的抖動現(xiàn)象。(當(dāng)然這也是使用了 content-visibility: auto
的一個小問題之一),不過明顯可以看出,這與我們通常使用 JavaScript 實(shí)現(xiàn)的虛擬列表非常類似。
當(dāng)然,在向下滾動的過程中,上方消失的已經(jīng)被渲染過且消失在視口的元素,也會因?yàn)橄г谝暱谥校匦卤浑[藏。因此,即便頁面滾動到最下方,整體的滾動條高度還是沒有什么變化的。
content-visibility
是否能夠優(yōu)化渲染性能?那么,content-visibility
是否能夠優(yōu)化渲染性能呢?
在 Youtube -- Slashing layout cost with content-visibility 中,給了一個非常好的例子。
這里我簡單復(fù)現(xiàn)一下。
對于一個存在巨量 HTML 內(nèi)容的頁面,譬如類似于這個頁面 -- HTML - Living Standard
可以感受到,往下翻,根本翻不到盡頭。(這里我在本地模擬了該頁面,復(fù)制了該頁面的所有 DOM,并非實(shí)際在該網(wǎng)站進(jìn)行測試)
如果不對這個頁面做任何處理,看看首次渲染需要花費(fèi)的時間:
可以看到,DOMContentLoaded 的時間的 3s+
,而花費(fèi)在 Rendering 上的就有整整 2900ms
!
而如果給這個頁面的每個段落,添加上 content-visibility: auto
,再看看整體的耗時:
可以看到,DOMContentLoaded 的時間驟降至了 500ms+
,而花費(fèi)在 Rendering 上的,直接優(yōu)化到了 61ms
!
2900ms --> 61ms,可謂是驚人級別的優(yōu)化了。因此,content-visibility: auto
對于長文本、長列表功能的優(yōu)化是顯而易見的。
contain-intrinsic-size
解決滾動條抖動問題當(dāng)然,content-visibility
也存在一些小問題。
從上面的例子,也能看到,在利用 content-visibility: auto
處理長文本、長列表的時候。在滾動頁面的過程中,滾動條一直在抖動,這不是一個很好的體驗(yàn)。
當(dāng)然,這也是許多虛擬列表都會存在的一些問題。
好在,規(guī)范制定者也發(fā)現(xiàn)了這個問題。這里我們可以使用另外一個 CSS 屬性,也就是文章一開頭提到的另外一個屬性 -- contain-intrinsic-size
,來解決這個問題。
contain-intrinsic-size
:控制由 content-visibility
指定的元素的自然大小。
什么意思呢?
還是上面的例子
...// ... 包含了 N 個 paragraph...
如果我們不使用 contain-intrinsic-size
,只對視口之外的元素使用 content-visibility: auto
,那么視口外的元素高度通常就為 0。
當(dāng)然,如果直接給父元素設(shè)置固定的
height
,也是會有高度的。
那么實(shí)際的滾動效果,滾動條就是抖動的:
所以,我們可以同時利用上 contain-intrinsic-size
,如果能準(zhǔn)確知道設(shè)置了 content-visibility: auto
的元素在渲染狀態(tài)下的高度,就填寫對應(yīng)的高度。如果如法準(zhǔn)確知道高度,也可以填寫一個大概的值:
.paragraph { content-visibility: auto; contain-intrinsic-size: 320px; }
如此之后,瀏覽器會給未被實(shí)際渲染的視口之外的 .paragraph
元素一個高度,避免出現(xiàn)滾動條抖動的現(xiàn)象:
你可以自己親自嘗試感受一下:CodePen Demo -- content-visibility: auto Demo
content-visibility: auto
VS LazyLoad那么,content-visibility: auto
是否可以替代LazyLoad(懶加載)呢?
我們來看看我們通常對于 LazyLoad(懶加載)的一個定義。
LazyLoad:通常而言,LazyLoad 的作用在于,當(dāng)頁面未滾動到相應(yīng)區(qū)域,該區(qū)域內(nèi)的資源(網(wǎng)絡(luò)請求)不會被加載。反之,當(dāng)頁面滾動到相應(yīng)區(qū)域,相關(guān)資源的請求才會被發(fā)起。
那么,如果 content-visibility: auto
要能夠替代 LazyLoad,則需要做到,初始化渲染的時候,在頁面當(dāng)前展示范圍外的,設(shè)定了 content-visibility: auto
的元素內(nèi)的一些靜態(tài)資源不會被加載。
這里我嘗試做了一個簡單的 DEMO:
還是借助上述的代碼,假設(shè)我們有如下的 HTML 結(jié)構(gòu),也就是在上述代碼基礎(chǔ)上,插入一些圖片資源:
...// ... 包含了 N 個 paragraph...
相應(yīng)設(shè)置下 CSS:
.paragraph, .g-img { content-visibility: auto; }
當(dāng)刷新頁面的時候,觀察網(wǎng)絡(luò)請求(Network)的狀況:
即便當(dāng)前頁面可視區(qū)域外的內(nèi)容未被渲染,但是圖片依然會被加載!
因此,這也得到了一個非常重要的結(jié)論:
content-visibility: auto
無法直接替代 LazyLoad,設(shè)置了 content-visibility: auto
的元素在可視區(qū)外只是未被渲染,但是其中的靜態(tài)資源仍舊會在頁面初始化的時候被全部加載。
所以,在實(shí)際使用中,如果你的業(yè)務(wù)中已經(jīng)使用了比較完善的 Lazyload 處理長列表或者一些圖片資源,那么 content-visibility: auto
不是更好的選擇。
當(dāng)然,content-visibility: auto
的特性又引申出了另外一個有意思的點(diǎn)。
如果說可視區(qū)外的內(nèi)容未被渲染,那是否會影響用戶進(jìn)行全文檢索呢?畢竟這是一個非常重要的功能。
我們再來做個探究,還是上面的 DEMO,我們在首尾添加兩個特殊的字符串:
content-visibility: auto 對搜索功能影響的探究
...// ... 包含了 N 個 paragraph...content-visibility: auto 對搜索功能影響的探究
相應(yīng)設(shè)置下 CSS:
.paragraph, .text { content-visibility: auto; }
好,如此一來,在頁面刷新后,第二個 .text
是處于未被渲染狀態(tài),我們試著全局 ctrl + F
查找一下,看看能找到幾個:
很有意思的現(xiàn)象,全局查找的時候,可以找到當(dāng)前未被渲染的元素內(nèi)的內(nèi)容。
這里,我們可以得到另外一個非常重要的點(diǎn):
即便存在設(shè)置了 content-visibility: auto
的未被渲染的元素,但是它并不會影響全局的搜索功能。
這也是 content-visibility
設(shè)計(jì)上充分的考慮,對可訪問性功能,或者說用戶體驗(yàn)的考量,有了這一點(diǎn),對于它的實(shí)際使用有著非常大的幫助。
content-visibility
的一些其他問題首先,看看 content-visibility
的兼容性(2022-06-03):
目前還是比較慘淡的,并且我沒有實(shí)際在業(yè)務(wù)中使用它,需要再等待一段時間。當(dāng)然,由于該屬性屬于漸進(jìn)增強(qiáng)一類的功能,即便失效,也完全不影響頁面本身的展示。
同時,也有一些同學(xué)表示,利用 content-visibility: auto
只能解決部分場景,在海量 DOM 的場景下的實(shí)際效果,還有待進(jìn)一步的實(shí)測。真正運(yùn)用的時候,多做對比,在做取舍。
當(dāng)然,現(xiàn)代瀏覽器已經(jīng)越來越智能,類似 content-visibility
功能的屬性也越來越多,我們在性能優(yōu)化的路上有了更多選擇,總歸是一件好事。
“怎么使用content-visibility屬性優(yōu)化渲染性能”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!