您好,登錄后才能下訂單哦!
這篇文章主要介紹“CSS怎么進(jìn)行性能優(yōu)化”,在日常操作中,相信很多人在CSS怎么進(jìn)行性能優(yōu)化問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”CSS怎么進(jìn)行性能優(yōu)化”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
想要優(yōu)化CSS的性能,我們首先需要了解CSS的渲染規(guī)則,CSS選擇器是從右向左進(jìn)行匹配的
來看個(gè)例子:
.nav h4 a{font-size: 14px;}復(fù)制代碼
渲染過程大概是:首先找到所有的a
,沿著a
的父元素查找h4
,然后再沿著h4
,查找.nav
。中途找到了符合匹配規(guī)則的節(jié)點(diǎn)就加入結(jié)果集。如果找到根元素html
都沒有匹配,則不再遍歷這條路徑,從下一個(gè)a
開始重復(fù)這個(gè)查找匹配(只要頁面上有多個(gè)最右節(jié)點(diǎn)為a
)。
Tips:為什么CSS選擇器是從右向左匹配的?
CSS中更多的選擇器是不會(huì)匹配的,所以在考慮性能問題時(shí),需要考慮的是如何在選擇器不匹配時(shí)提升效率。從右向左匹配就是為了達(dá)成這一目的的,通過這一策略能夠使得CSS選擇器在不匹配的時(shí)候效率更高。這樣想來,在匹配時(shí)多耗費(fèi)一些性能也能夠想的通了。
性能優(yōu)化中有一個(gè)重要的指標(biāo)——首次有效繪制(First Meaningful Paint,簡稱FMP)即指頁面的首要內(nèi)容(primary content)出現(xiàn)在屏幕上的時(shí)間。這一指標(biāo)影響用戶看到頁面前所需等待的時(shí)間,而 內(nèi)聯(lián)首屏關(guān)鍵CSS(即Critical CSS,可以稱之為首屏關(guān)鍵CSS) 能減少這一時(shí)間。
很多人都喜歡通過link
標(biāo)簽引用外部CSS文件
。但需要知道的是,將CSS直接內(nèi)聯(lián)到HTML文檔中能使CSS更快速地下載。而使用外部CSS文件時(shí),需要在HTML文檔下載完成后才知道所要引用的CSS文件,然后才下載它們。所以說,內(nèi)聯(lián)CSS能夠使瀏覽器開始頁面渲染的時(shí)間提前,因?yàn)樵贖TML下載完成之后就能渲染了。
但是我們不應(yīng)該將所有的CSS都內(nèi)聯(lián)在HTML文檔中,因?yàn)閇初始擁塞窗口]存在限制(TCP相關(guān)概念,通常是 14.6kB,壓縮后大小)
,如果內(nèi)聯(lián)CSS后的文件超出了這一限制,系統(tǒng)就需要在服務(wù)器和瀏覽器之間進(jìn)行更多次的往返,這樣并不能提前頁面渲染時(shí)間。因此,我們應(yīng)當(dāng)只將渲染首屏內(nèi)容所需的關(guān)鍵CSS內(nèi)聯(lián)到HTML中。
??還有一點(diǎn)需要注意的是內(nèi)聯(lián)CSS沒有緩存,每次都會(huì)隨HTML的加載而重新下載,但我們將內(nèi)聯(lián)首屏關(guān)鍵CSS控制在 14.6kB
以內(nèi),它對性能優(yōu)化還是起到正向作用的。(凡事有利也有弊)
我們需要知道兩點(diǎn)內(nèi)容:(具體可以看我之前的文章:這些瀏覽器面試題,看看你能回答幾個(gè)?)
CSS
不會(huì)阻塞DOM
的解析,但會(huì)阻塞DOM
的渲染
CSS
會(huì)阻塞JS
執(zhí)行,但不會(huì)阻塞JS
文件的下載
由于CSS會(huì)阻塞DOM的渲染,所以我們將首屏關(guān)鍵CSS內(nèi)聯(lián)后,剩余的非首屏CSS內(nèi)容可以使用外部CSS,并且異步加載,防止非首屏CSS內(nèi)容阻塞頁面的渲染。
CSS異步加載方式
第一種方法是動(dòng)態(tài)創(chuàng)建
// 創(chuàng)建link標(biāo)簽 const myCSS = document.createElement( "link" ); myCSS.rel = "stylesheet"; myCSS.href = "mystyles.css"; // 插入到header的最后位置 document.head.insertBefore( myCSS, document.head.childNodes[ document.head.childNodes.length - 1 ].nextSibling );
第二種方法是將link元素的media
屬性設(shè)置為用戶瀏覽器不匹配的媒體類型(或媒體查詢)
對瀏覽器來說,如果樣式表不適用于當(dāng)前媒體類型,其優(yōu)先級會(huì)被放低,會(huì)在不阻塞頁面渲染的情況下再進(jìn)行下載。在首屏文件加載完成之后,將media
的值設(shè)為screen
或all
,從而讓瀏覽器開始解析CSS。
<link rel="stylesheet" href="mystyles.css" media="noexist" onload="this.media='all'">
第三種方法是通過rel
屬性將link
元素標(biāo)記為alternate
可選樣式表
<link rel="alternate stylesheet" href="mystyles.css" onload="this.rel='stylesheet'">
第四種方法是使用rel=preload
來異步加載CSS
<link rel="preload" href="mystyles.css" as="style" onload="this.rel='stylesheet'">
注意,as
是必須的。忽略as
屬性,或者錯(cuò)誤的as
屬性會(huì)使preload
等同于XHR
請求,瀏覽器不知道加載的是什么內(nèi)容,因此此類資源加載優(yōu)先級會(huì)非常低。as
的可選值可以參考上述標(biāo)準(zhǔn)文檔。
看起來,rel="preload"
的用法和上面兩種沒什么區(qū)別,都是通過更改某些屬性,使得瀏覽器異步加載CSS文件但不解析,直到加載完成并將修改還原,然后開始解析。
但是它們之間其實(shí)有一個(gè)很重要的不同點(diǎn),那就是使用preload,比使用不匹配的media
方法能夠更早地開始加載CSS。所以盡管這一標(biāo)準(zhǔn)的支持度還不完善,仍建議優(yōu)先使用該方法。
這應(yīng)該是最容易想到的一個(gè)方法了,通過壓縮CSS文件大小來提高頁面加載速度?,F(xiàn)在的構(gòu)建工具,如webpack、gulp/grunt、rollup等也都支持CSS壓縮功能。壓縮后的文件能夠明顯減小,可以大大降低了瀏覽器的加載時(shí)間。
一般情況下,元素的嵌套層級不能超過3級,過度的嵌套會(huì)導(dǎo)致代碼變得臃腫,沉余,復(fù)雜。導(dǎo)致css文件體積變大,造成性能浪費(fèi),影響渲染的速度!而且過于依賴HTML文檔結(jié)構(gòu)。這樣的css樣式,維護(hù)起來,極度麻煩,如果以后要修改樣式,可能要使用!important
覆蓋。盡量保持簡單,不要使用嵌套過多過于復(fù)雜的選擇器。
一般情況下,會(huì)存在這兩種無用的CSS代碼:一種是不同元素或者其他情況下的重復(fù)代碼,一種是整個(gè)頁面內(nèi)沒有生效的CSS代碼。
對于前者,在編寫的代碼時(shí)候,我們應(yīng)該盡可能地提取公共類,減少重復(fù)。對于后者,在不同開發(fā)者進(jìn)行代碼維護(hù)的過程中,總會(huì)產(chǎn)生不再使用的CSS的代碼,當(dāng)然一個(gè)人編寫時(shí)也有可能出現(xiàn)這一問題。而這些無用的CSS代碼不僅會(huì)增加瀏覽器的下載量,還會(huì)增加瀏覽器的解析時(shí)間,這對性能來說是很大的消耗。所以我們需要找到并去除這些無用代碼。
那么我們?nèi)绾沃滥男〤SS代碼是無用代碼呢?
谷歌的Chrome瀏覽器就有這種開箱即用的功能。只需轉(zhuǎn)到查看>開發(fā)人員>開發(fā)人員工具,并在最近的版本中打開Sources選項(xiàng)卡,然后打開命令菜單。然后,點(diǎn)擊Coverage,在Coverage analysis窗口中高亮顯示當(dāng)前頁面上未使用的代碼。
我們有時(shí)候可能會(huì)寫下面這種代碼來消除一些標(biāo)簽的默認(rèn)樣式或統(tǒng)一瀏覽器對標(biāo)簽渲染的差異化:
*{ margin:0; padding:0; }
這樣雖然代碼量少,但它的性能可不是最佳的,我們最好還是寫對應(yīng)的標(biāo)簽選擇器:
body,dl,dd,h2,h3,h4,h5,h6,h7,p,form,ol,ul{ margin:0; padding:0; }
開發(fā)時(shí)盡量避免使用通配符選擇器
一般來講一個(gè)網(wǎng)站上肯定會(huì)有很多個(gè)小圖標(biāo),對于這些小圖標(biāo),目前的主流的解決方案有三個(gè),cssSprite(雪碧圖),字體圖標(biāo),把圖片轉(zhuǎn)成base64。
cssSprite: 把所有icon圖片合成一張png圖片,使用時(shí)對節(jié)點(diǎn)設(shè)置寬高,加上bacgroud-position進(jìn)行背景定位。以背景圖方式顯展示需要的icon,如果一個(gè)網(wǎng)站有20圖標(biāo),那么就要請求20次,使用cssSprite
,只需要請求一次,大大的減少了http請求。缺點(diǎn)就是管理不靈活,如果需要新增一個(gè)圖標(biāo),都需要改合并圖片的源文件,圖標(biāo)定位也要規(guī)范,不然容易干擾圖片之間的定位。
字體圖標(biāo): 簡單粗暴的理解就是把所有的圖標(biāo)當(dāng)成一個(gè)字體處理!這樣不用去請求圖片。一般是使用class來定義圖標(biāo),要替換圖標(biāo)時(shí),只需更換樣式名,管理方便,語意明確,靈活放大縮小,并且不會(huì)造成失真。但是只支持單色的圖片。
base64: 另一種方案就是把小的icon圖片轉(zhuǎn)成base64編碼,這樣可以不用去請求圖片,把base64編碼直接整合到j(luò)s或者css里面,可以防止因?yàn)橐恍┫鄬β窂?,或者圖片被不小刪除了等問題導(dǎo)致圖片404錯(cuò)誤。但是找個(gè)方式會(huì)生成一大串的base64編碼。一般來說,8K以下的圖片才轉(zhuǎn)換成base64編碼。如果把一張50K的圖片轉(zhuǎn)成base64編碼,那么會(huì)生成超過65000個(gè)字符的base64編碼,字符的大小就已經(jīng)是將近70K了!建議就是:8K以下的圖片才轉(zhuǎn)換成base64編碼。
不建議使用@import
主要有以下兩點(diǎn)原因:
使用@import
引入CSS會(huì)影響瀏覽器的并行下載。使用@import
引用的CSS文件只有在引用它的那個(gè)css文件被下載、解析之后,瀏覽器才會(huì)知道還有另外一個(gè)css需要下載,這時(shí)才去下載,然后下載后開始解析、構(gòu)建render tree等一系列操作。這就導(dǎo)致瀏覽器無法并行下載所需的樣式文件。
多個(gè)@impor
t會(huì)導(dǎo)致下載順序紊亂。在IE中,@import
會(huì)引發(fā)資源文件的下載順序被打亂,即排列在@import后面的js文件先于@import下載,并且打亂甚至破壞@import自身的并行下載。
在ID選擇器前面嵌套其它選擇器純粹是多余的
ID選擇器本來就是唯一的而且人家權(quán)值那么大,前面嵌套(.content #text
)完全是浪費(fèi)性能。
除了嵌套,在ID選擇器前面也不需要加標(biāo)簽或者其它選擇器。比如 div#text
或者.box#text
。這兩種方式完全是多余的,理由就是ID在頁面就是唯一的。前面加任何東西都是多余的!
CSS 支持多種單位和數(shù)字格式,可以刪除尾隨和跟隨的零,零始終是零,添加維度不會(huì)為包含的信息附帶任何價(jià)值。
.box { padding: .2px; margin: 20px; avalue: 0; }
在網(wǎng)站的使用過程中,某些操作會(huì)導(dǎo)致樣式的改變,這時(shí)瀏覽器需要檢測這些改變并重新渲染,其中有些操作所耗費(fèi)的性能更多。我們都知道,當(dāng)FPS為60時(shí),用戶使用網(wǎng)站時(shí)才會(huì)感到流暢。這也就是說,我們需要在16.67ms內(nèi)完成每次渲染相關(guān)的所有操作,所以我們要盡量減少耗費(fèi)更多的操作。
減少回流與重繪
合并對DOM
樣式的修改,采用css class
來修改
const el = document.querySelector('.box') el.style.margin = '5px' el.style.borderRadius = '12px' el.style.boxShadow = '1px 3px 4px #ccc'
建議使用css class
.update{ margin: 5px; border-dadius: 12px; box-shadow: 1px 3px 4px #ccc } const el = document.querySelector('.box') el.classList.add('update')
如果需要對DOM進(jìn)行多次訪問,盡量使用局部變量緩存該DOM
避免使用table布局,可能很?的?個(gè)?改動(dòng)會(huì)造成整個(gè)table的重新布局
CSS選擇符從右往左匹配查找,避免節(jié)點(diǎn)層級過多
DOM離線處理,減少回流重繪次數(shù)
離線的DOM不屬于當(dāng)前DOM樹中的任何一部分,這也就意味著我們對離線DOM處理就不會(huì)引起頁面的回流與重繪。
使用display: none
,上面我們說到了 (display: none
) 將元素從渲染樹中完全移除,元素既不可見,也不是布局的組成部分,之后在該DOM上的操作不會(huì)觸發(fā)回流與重繪,操作完之后再將display
屬性改為顯示,只會(huì)觸發(fā)這一次回流與重繪。
提醒?:visibility : hidden
的元素只對重繪有影響,不影響重排。
通過 documentFragment 創(chuàng)建一個(gè) dom
文檔片段,在它上面批量操作 dom
,操作完成之后,再添加到文檔中,這樣只會(huì)觸發(fā)一次重排。
const el = document.querySelector('.box') const fruits = ['front', 'nanjiu', 'study', 'code']; const fragment = document.createDocumentFragment(); fruits.forEach(item => { const li = document.createElement('li'); li.innerHTML = item; fragment.appendChild(li); }); el.appendChild(fragment);
克隆節(jié)點(diǎn),修改完再替換原始節(jié)點(diǎn)
const el = document.querySelector('.box') const fruits = ['front', 'nanjiu', 'study', 'code']; const cloneEl = el.cloneNode(true) fruits.forEach(item => { const li = document.createElement('li'); li.innerHTML = item; cloneEl.appendChild(li); }); el.parentElement.replaceChild(cloneEl,el)
DOM脫離普通文檔流
使用absoult
或fixed
讓元素脫離普通文檔流,使用絕對定位會(huì)使的該元素單獨(dú)成為渲染樹中 body
的一個(gè)子元素,重排開銷比較小,不會(huì)對其它節(jié)點(diǎn)造成太多影響。
CSS3硬件加速(GPU加速)
使用css3硬件加速,可以讓transform、opacity、filters
這些動(dòng)畫不會(huì)引起回流重繪 。但是對于動(dòng)畫的其它屬性,比如background-color
這些,還是會(huì)引起回流重繪的,不過它還是可以提升這些動(dòng)畫的性能。
常見的觸發(fā)硬件加速的css屬性:
transform
opacity
filters
Will-change
將節(jié)點(diǎn)設(shè)置為圖層
圖層能夠阻?該節(jié)點(diǎn)的渲染?為影響別的節(jié)點(diǎn)。?如對于video標(biāo)簽來說,瀏覽器會(huì)?動(dòng)將該節(jié)點(diǎn)變?yōu)閳D層。
到此,關(guān)于“CSS怎么進(jìn)行性能優(yōu)化”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。