Web標準是一系列標準的集合。這些標準大概分三方面:結構、表現和行爲。結構化主要有HTML, XHTML和XML,表現主要有CSS,行爲標準主要包括對象模型,如 W3C DOM、ECMAScript等。這些標準大部分是右W3C起草和發佈的。php
1、簡單介紹一下什麼是瀏覽器內核。
瀏覽器最重要或者說核心的部分是「Rendering Engine」,可大概譯爲「解釋引擎」,不過咱們通常習慣將之稱爲「瀏覽器內核」。負責對網頁語法的解釋(如HTML、JavaScript)並渲染(顯示)網頁。 因此,一般所謂的瀏覽器內核也就是瀏覽器所採用的渲染引擎,渲染引擎決定了瀏覽器如何顯示網頁的內容以及頁面的格式信息。不一樣的瀏覽器內核對網頁編寫語法的解釋也有不一樣,所以同一網頁在不一樣的內核的瀏覽器裏的渲染(顯示)效果也可能不一樣,這也是網頁編寫者須要在不一樣內核的瀏覽器中測試網頁顯示效果的緣由。css
Web頁面運行在各類各樣的瀏覽器當中,瀏覽器載入、渲染頁面的速度直接影響着用戶體驗簡單地說,頁面渲染就是瀏覽器將html代碼根據CSS定義的規則顯示在瀏覽器窗口中的這個過程。先來大體瞭解一下瀏覽器都是怎麼幹活的:
1. 用戶輸入網址(假設是個html頁面,而且是第一次訪問),瀏覽器向服務器發出請求,服務器返回html文件;
2. 瀏覽器開始載入html代碼,發現<head>標籤內有一個<link>標籤引用外部CSS文件;
3. 瀏覽器又發出CSS文件的請求,服務器返回這個CSS文件;
4. 瀏覽器繼續載入html中<body>部分的代碼,而且CSS文件已經拿到手了,能夠開始渲染頁面了;
5. 瀏覽器在代碼中發現一個<img>標籤引用了一張圖片,向服務器發出請求。此時瀏覽器不會等到圖片下載完,而是繼續渲染後面的代碼;
6. 服務器返回圖片文件,因爲圖片佔用了必定面積,影響了後面段落的排布,所以瀏覽器須要回過頭來從新渲染這部分代碼;
7. 瀏覽器發現了一個包含一行Javascript代碼的<script>標籤,趕快運行它;
8. Javascript腳本執行了這條語句,它命令瀏覽器隱藏掉代碼中的某個html
瀏覽器天天就這麼來來回回跑着,要知道不一樣的人寫出來的html和css代碼質量良莠不齊,說不定哪天跑着跑着就掛掉了。好在這個世界還有這麼一羣人——頁面重構工程師,平時挺不起眼,也就幫視覺設計師們切切圖啊改改字,其實背地裏仍是幹了很多實事的。前端
說到頁面爲何會慢?那是由於瀏覽器要花時間、花精力去渲染,尤爲是當它發現某個部分發生了點變化影響了佈局,須要倒回去從新渲染,內行稱這個回退的過程叫reflow。程序員
reflow幾乎是沒法避免的。如今界面上流行的一些效果,好比樹狀目錄的摺疊、展開(實質上是元素的顯示與隱藏)等,都將引發瀏覽器的 reflow。鼠標滑過、點擊……只要這些行爲引發了頁面上某些元素的佔位面積、定位方式、邊距等屬性的變化,都會引發它內部、周圍甚至整個頁面的從新渲染。一般咱們都沒法預估瀏覽器到底會reflow哪一部分的代碼,它們都彼此相互影響着。web
reflow問題是能夠優化的,咱們能夠儘可能減小沒必要要的reflow。好比開頭的例子中的<img>圖片載入問題,這其實就是一個能夠避免的reflow——給圖片設置寬度和高度就能夠了。這樣瀏覽器就知道了圖片的佔位面積,在載入圖片前就預留好了位置。chrome
另外,有個和reflow看上去差很少的術語:repaint,中文叫重繪。 若是隻是改變某個元素的背景色、文字顏色、邊框顏色等等不影響它周圍或內部佈局的屬性,將只會引發瀏覽器repaint。repaint的速度明顯快於 reflow(在IE下須要換一下說法,reflow要比repaint 更緩慢)。後端
3、從瀏覽器的渲染原理講CSS性能(http://hi.baidu.com/zhoumm1008/blog/item/03fa88f97fe5ddebfd037f4b.html)瀏覽器
平時咱們幾乎天天都在和瀏覽器打交道,寫出來的頁面頗有可能在不一樣的瀏覽器下顯示的不同。苦逼的前端攻城師們爲了兼容各個瀏覽器而不斷地去測試和調試,還在腦子中記下各類遇到的BUG及解決方案,而咱們好像並無去主動地關注和了解下瀏覽器的工做原理。若是咱們對此作一點了解,我想在項目過程當中就能夠根據它有效的避免一些問題以及對頁面性能作出相應的改進。今天咱們主要根據瀏覽器的渲染原理對CSS的書寫性能作一點改進(固然還有JS本篇文章暫不考慮,後面的文章會作介紹),下面讓咱們一塊兒來揭開瀏覽器的渲染原理這一神祕的面紗吧:安全
最終決定瀏覽器表現出來的頁面效果的差別是:渲染引擎 Rendering Engine(也叫作排版引擎),也就是咱們一般所說的「瀏覽器內核」,負責解析網頁語法(如HTML、JavaScript)並渲染、展現網頁。相同的代碼在不一樣的瀏覽器呈現出來的效果不同,那麼就頗有多是不一樣的瀏覽器內核致使的。
咱們來看一下加載頁面時瀏覽器的具體工做流程(圖一):
(圖一)
一、解析HTML以重建DOM樹(Parsing HTML to construct the DOM tree ):渲染引擎開始解析HTML文檔,轉換樹中的標籤到DOM節點,它被稱爲「內容樹」。
二、構建渲染樹(Render tree construction):解析CSS(包括外部CSS文件和樣式元素),根據CSS選擇器計算出節點的樣式,建立另外一個樹 —- 渲染樹。
三、佈局渲染樹(Layout of the render tree): 從根節點遞歸調用,計算每個元素的大小、位置等,給每一個節點所應該出如今屏幕上的精確座標。
四、繪製渲染樹(Painting the render tree) : 遍歷渲染樹,每一個節點將使用UI後端層來繪製。
主要的流程就是:構建一個dom樹,頁面要顯示的各元素都會建立到這個dom樹當中,每當一個新元素加入到這個dom樹當中,瀏覽器便會經過css引擎查遍css樣式表,找到符合該元素的樣式規則應用到這個元素上。
注意了:css引擎查找樣式表,對每條規則都按從右到左的順序去匹配。 看以下規則:
1 | #nav li {} |
看起來很快,實際上很慢,儘管這讓人有點費解#_#。咱們中的大多數人,尤爲是那些從左到右閱讀的人,可能猜測瀏覽器也是執行從左到右匹配規則的,所以會推測這條規則的開銷並不高。在腦海中,咱們想象瀏覽器會像這樣工做:找到惟一的ID爲nav的元素,而後把這個樣式應用到直系子元素的li元素上。咱們知道有一個ID爲nav的元素,而且它只有幾個Li子元素,因此這個CSS選擇符應該至關高效。
事實上,CSS選擇符是從右到左進行匹配的。瞭解這方面的知識後,咱們知道這個以前看似高效地規則實際開銷至關高,瀏覽器必須遍歷頁面上每一個li元素並肯定其父元素的id是否爲nav。
1 | *{} |
額,這種方法我剛寫CSS的也寫過,卻不知這種效率是差到極點的作法,由於*通配符將匹配全部元素,因此瀏覽器必須去遍歷每個元素,這樣的計算次數多是上萬次!
1 | ul#nav{} ul.nav{} |
在頁面中一個指定的ID只能對應一個元素,因此沒有必要添加額外的限定符,並且這會使它更低效。同時也不要用具體的標籤限定類選擇符,而是要根據實際的狀況對類名進行擴展。例如把ul.nav改爲.main_nav更好。
1 | ul li li li .nav_item{} |
對於這樣的選擇器,以前也寫過,最後本身也數不過來有多少後代選擇器了,何不用一個類來關聯最後的標籤元素,如.extra_navitem,這樣只須要匹配class爲extra_navitem的元素,效率明顯提高了
對此,在CSS書寫過程當中,總結出以下性能提高的方案:
選用高效的選擇符,能夠減小頁面的渲染時間,從而有效的提高用戶體驗(頁面越快,用戶固然越喜歡^_^),你能夠看一下CSS selectors Test,這個實驗的重點是評估複雜選擇符和簡單選擇符的開銷。也許當你想讓渲染速度最高效時,你可能會給每一個獨立的標籤配置一個ID,而後用這些ID寫樣式。那的確會超級快,也超級荒唐!這樣的結果是語義極差,後期的維護難到了極點。
但說到底,CSS性能這東西對於小的項目來說可能真的是微乎其微的東西,提高可能也不是很明顯,但對於大型的項目確定是有幫助的。並且一個好的CSS書寫習慣和方式可以幫助咱們更加嚴謹的要求本身。