本文原創:fanjiayucss
chrome團隊提出了一個以用戶爲中心的性能模型被稱爲RAIL,它爲工程師提供一個目標,只要達到目標的網頁,用戶就會以爲很流暢;它將用戶體驗拆解爲一些關鍵操做,例如:點擊,加載等;並給這些操做規定一個目標,例如:點擊一個按鈕後,多長時間給反饋用戶會以爲流暢。html
RAIL將影響性能的行爲劃分爲四個方面,分別是:response(響應)、animation(動畫)、idle(空閒)與load(加載)。沒錯,RAIL這個名字來自於這四個單詞的首字母,方便記憶。css3
JavaScript:通常來講,咱們會使用JavaScript來實現一些視覺變化的效果。chrome
Style:計算樣式。這個過程是根據CSS選擇器,對每一個DOM元素匹配對應的CSS樣式。瀏覽器
Layout:佈局。具體計算每一個DOM元素最終在屏幕上顯示的大小和位置。Web頁面中元素的佈局是相對的,所以一個元素的佈局發生變化,會聯動地引起其餘元素的佈局發生變化。所以,對於瀏覽器而言,佈局過程是常常發生的。bash
Paint:繪製。本質上就是**填充像素的過程。**包括繪製文字、顏色、圖像、邊框和陰影等,也就是一個DOM元素全部的可視效果。通常來講,這個繪製過程是在多個層上完成的。佈局
Composite:渲染層合併。性能
若是你修改一個DOM元素的「layout」屬性,也就是改變了元素的樣式(好比width、height或者position等),那麼瀏覽器會檢查哪些元素須要從新佈局,而後對頁面激發一個reflow(重排)過程完成從新佈局。reflow一定會引起重繪,這對於WEB的性能影響是極大的。測試
影響WEB性能主要過程包括layout、paint和composite。那麼對於cssanimation而言,咱們的全部操做都是經過CSS的樣式控制動畫,只要是會觸發layout、paint和composite的CSS屬性都會直接影響動畫的性能。因此整個動畫應儘可能避開重排和重繪。字體
會觸發重排重繪:調整窗口大小、改變字體、增長或者移除樣式表、內容變化、激活CSS僞類、計算offsetwidth和offsetheight等等。
影響layout的CSS屬性:csstriggers.com/
####防止FSL(強制同步佈局)
以下代碼爲會觸發FSL的一段代碼
<body>
<button id="btn">Click me~</button>
<div class="container">
<!-- 建立多個class爲box的div使效果更明顯>
<div class="box"></div>
</div>
<script>
const btn = document.querySelector('#btn');
const container = document.querySelector('.container');
const boxes = document.querySelectorAll('.box');
btn.onclick = function () {
for (var i = 0; i < boxes.length; i++) {
boxes[i].style.width = container.offsetWidth + 'px';
}
}
</script>
</body>
複製代碼
對代碼進行以下優化
<script>
const btn = document.querySelector('#btn');
const container = document.querySelector('.container');
const boxes = document.querySelectorAll('.box');
btn.onclick = function () {
const newWidth = container.offsetWidth;
for (var i = 0; i < boxes.length; i++) {
boxes[i].style.width = newWidth + 'px';
}
}
</script>
複製代碼
從對比中能夠看出,前者的Rendering是後者的幾倍之多,可見,優化重排重繪,防止FSL的發生對性能的提高效果是很明顯的。
####新建圖層
事實上瀏覽器在渲染頁面時,能夠將頁面分爲不少個圖層,有點相似於photoshop,一張圖片在potoshop中是由多個圖層組合而成,而瀏覽器最終顯示的頁面實際也是由多個圖層構成的。
因此將本來不斷髮生變化的元素提高到單獨的圖層中,就再也不須要繪製了,瀏覽器只須要將兩個圖層合併在一塊兒便可。(注:圖層的維護也須要成本,不要一味地不斷新建圖層)
<body>
<div class="ball-running" style="width:100px;height:50px;background:red;position:absolute;left:0;top:0"></div>
</body>
<style>
.ball-running { animation: run-around 4s infinite;}
@keyframes run-around {
0%: { top: 0; left: 0; }
25% { top: 0; left: 200px; }
50% { top: 200px; left: 200px; }
75% { top: 200px; left: 0; }
}
</style>
複製代碼
<body>
<div class="ball-running" style="width:100px;height:50px;background:red;position:absolute;left:0;top:0"></div>
</body>
<style>
.ball-running { animation: run-around 4s infinite; }
@keyframes run-around {
0%: { transform: translate(0, 0); }
25% { transform: translate(200px, 0); }
50% { transform: translate(200px, 200px); }
75% { transform: translate(0, 200px); }
}
</style>
複製代碼
JS動畫要保證預留出6ms的時間給瀏覽器處理像素管道,而自身執行時間應該小於10ms來保證總體運行速度小於16ms。
避免一切FSL,它很是影響性能。
CSS動畫儘可能使用transform屬性來完成動畫。建議使用transform的translate替代margin或position中的top、right、bottom和left,同時使用transform中的scalex或者scaley來替代width和height。