原文地址css
你也許早已在項目中使用上了Animations 或 Transitions(若是尚未,能夠閱讀CSS-Trick’s almanac 關於animations或transitions的相關文章)。你會發現你的一些運動表現流暢,而另外一些卻不盡如人意,你想知道緣由?web
本文將闡述瀏覽器是怎樣處理CSS animations 與 transitions。以期在編寫代碼以前,你能夠經過直覺判斷某一運動可否運行良好。經過這種直覺,你將能過作出瀏覽器親和且用戶體驗流暢的設計決策。瀏覽器
讓我深刻瀏覽器內部一探究竟。只有理解了它的工做用力,咱們才能作的更好。佈局
現代瀏覽器有兩個重要的執行線程。兩個線程共同協做來渲染web頁面。他們是:性能
主線程(The main thread)動畫
排版線程(The compositor thread)spa
通常來講,主線程負責:線程
運行JS代碼設計
計算HTML元素的CSS樣式3d
佈局頁面
將元素繪製成一副或多幅位圖
將位圖傳給排版線程
排版線程則負責:
經過GPU,將位圖繪製到屏幕上
對可見或即將可見的區域,詢問主線程是否進行位圖更新。
計算頁面的可見區域
當滾動屏幕時,計算出即將可見的區域
當滾動時移動頁面區域
主線程花費大量的時間忙於執行JS代碼與繪製大型元素。主線程正在處理任務時,他將沒法響應用戶的輸入(注:這裏是廣義的輸入,泛指交互)。
另外一方面,排版線程保持着對用戶的輸入的響應。當頁面改變時,排版線程會進行每秒60次的重繪。甚至在頁面還不完整時。
例如,當用戶滾動頁面時,排版線程會詢問主線程是否爲新的可見區域更新位圖。然而,當主線程的反饋不那麼迅速時,排版線程並不會等待。他將對已有反饋的頁面進行繪製並使用空白代替未反饋的部分。
上文提到排版線程經過GPU將位圖繪製到屏幕上。讓咱們聊一聊GPU。
GPU是現今大多數手機,平板,電腦的組成部分。它是一個至關專門化的部件,這意味着它只專一處理一些事務。
GPUs 可以快速處理:
把圖形繪製到屏幕上
重複繪製位圖
在不一樣的區域繪製相同位圖或將位圖旋轉,縮放。
如今咱們對瀏覽網頁時,硬件與軟件的大體行爲。讓咱們來看看究竟瀏覽器的兩個線程是如何協同運做來完成一個CSS動畫的。
假設咱們使用以下代碼,將一個元素從100px變爲200px:
div { height: 100px; transition: height 1s linear; } div:hover { height: 200px; }
兩個線程將會按照下圖示意的操做執行。橙色框中的操做會消耗大量時間,而藍色框的操做運行迅速。
如圖,這一過程當中有大量的黃色框,這意味着瀏覽器並不能流暢運行。過渡動畫將會卡頓。
在每一幀的過渡動畫,瀏覽器都將執行佈局,繪製以及向GPC內存更新新的位圖的操做。如咱們所知,向GPU內存加載位圖是一個至關緩慢的操做。
瀏覽器每一幀運行不流暢的緣由在於元素的內容在持續變化。變化元素的高度意味着其子元素的形狀也跟着改變,所以瀏覽器要進行佈局。佈局後,主線程要爲元素重新生成位圖。
所以,改變高度是一種高代價的過渡動畫。那麼有什麼的代價比較低廉?
假設咱們將一個元素的尺寸從一半還原會正常尺寸。同時,假設使用CSS transform 屬性去縮放,採用過渡完成動畫,代碼以下:
div { transform: scale(0.5); transition: transform 1s linear; } div:hover { transform: scale(1.0); }
讓咱們看看這個過程的示意圖:
此次橙色框明顯減小,這意味着動畫更加流暢。元素transform 變化與高度變化的動畫究竟區別在哪?
經過定義,CSS transform 屬性並無改變元素與相鄰元素的佈局,僅僅只影響了做爲一個總體的元素自身(縮放,旋轉整個元素或移動整個元素)。
這對於瀏覽器來講是個好消息。瀏覽器僅須要產生元素的位圖,並在動畫開始時向GPU更新位圖。以後,瀏覽器不用再作更多的佈局,繪製和位圖更新操做。取而代之的是,仰仗GPU專業的能力在不一樣的區域繪製相同的位圖,或使之旋轉,縮放。
如此,是否意味着不該進行元素高度的動畫?不,有時這仰賴你的設計,運動一樣能運行的足夠快。也許你的元素是獨立的,並不會形成其它部分的重排。也許你的元素只是簡單的重繪,瀏覽器能夠快速地執行。也許你的元素很小,瀏覽器只要向GPU更新一個小的位圖。
固然,若是你的動畫使用像CSS transform同樣的「廉價」屬性替代像CSS height的更「昂貴」的屬性,而且這不影響你的設計理念,那就這樣作吧。例如,當你的設計須要一個按鈕在點擊時顯示菜單,你須要嘗試元素的transform屬性來顯示菜單而不是經過使用top或height屬性來實現相同或類似的效果。
下面列出一些能實現快速動畫的CSS屬性:
CSS transform
CSS opacity
CSS filter (取決於filter的複雜程度與瀏覽器性能)
這個列表如今看來可能頗有限,但隨着瀏覽器的進步,愈來愈多的屬性會運動地更快。同時,只是用這個列表上的屬性,你也會驚歎於僅僅經過使用這些屬性的組合就能創造出大量豐富的效果。