1. 程式人生 > >CSS 寫作建議和效能優化小結

CSS 寫作建議和效能優化小結

1.前言

還有幾天就到國慶中秋了,快要放假了,先祝大家節日快樂!之前寫過 JS 的寫作建議和技巧,那麼今天就來聊聊 CSS 吧!

說到 CSS,每一個網頁都離不開 CSS,但是對於 CSS,很多開發者的想法就是,CSS 只要能用來佈局,把效果圖排出來就可以了,其它的細節或者優化,不需要怎麼考慮。但是我覺得 CSS 可不只是把頁面的佈局完成就是完事的,還需要考慮很多細節有優化,更不會像大家想得那麼簡單。在學習當中,如果發現什麼技巧或者優化的點,我也會學以致用!

那麼今天,就分享下我總結的 CSS 寫作建議和效能優化的一些問題!希望能幫讓大家對神奇的 CSS 有一個新認識。當然,如果大家覺得還有什麼其它的建議,歡迎指點!

2.CSS 渲染規則

首選,關於CSS 渲染的規則,大家可能都知道,是從右到左的渲染!如下栗子:

1 .nav h3a{font-size:14px;}

渲染過程大概是:首先找到所有的a,沿著a的父元素查詢h3,然後再沿著h3,查詢.nav。中途找到了符合匹配規則的節點就加入結果集。如果找到根元素html都沒有匹配,則不再遍歷這條路徑,從下一個a開始重複這個查詢匹配(只要頁面上有多個最右節點為a

)。

3.巢狀層級不要超過 3 級

一般情況下,元素的巢狀層級不能超過 3 級,過度的巢狀會導致程式碼變得臃腫、沉餘、複雜,導致 CSS 檔案體積變大,造成效能浪費,影響渲染的速度,而且過於依賴 HTML 文件結構。這樣的 CSS 樣式,維護起來,極度麻煩,如果以後要修改樣式,可能要使用!important覆蓋。

4.樣式重置

這個我目前保持中立意見,因為看著網上的文章,有些人支援使用樣式重置,有些人不支援使用,誰也說服不了誰。我自己的情況,我有使用樣式重置,但是是比較簡單的一個總結,程式碼如下!

12345678910111213141516171819202122232425262728293031323334 body,dl,dd,h1,h2,h3,h4,h5,h6,p,form,ol,ul{margin:0;padding:0;}h1,h2,h3,h4,h5,h6{font-weight:normal;}ol,ul{list-style:none;}h1{font-size:24px;}h2{font-size:20px;}h3{font-size:18px;}h4{font-size:16px;}h5{font-size:14px;}h6{font-size:12px;}

5.樣式級別

首先,CSS 樣式級別整理如下:

!important > 行內樣式 > ID 樣式 > Class 樣式 > 標籤名樣式。

然後有一點要提一下就是,組合選擇器使用權值會疊加的。比如 ID 的權值是100,Class 是10,標籤名是 1(其它不清楚了)!那麼div.test-class權值就是 11,div#test就是 101.

比如有一個 div:

1 <div id="test"class="test-class"style="color:green;"/>

那麼樣式權值方面就是:

  • div {color: red !improtant;}(大於下面的一切)
  • <div id="test" class="test-class" style="color:black;"></div>(大於 111)
  • div#test.test-class(111)
  • #id.test-class(110)
  • div#test(101)
  • #test(100)
  • div.test-class(11)
  • .test-class(10)
  • div(1)
  • *(小於 1)

6.inline-block 的邊距

不解釋,看圖:

上面幾個p元素marginpadding都為0,但是還有邊距。這個的解決方案有兩種:

  1. 刪除程式碼之前的空行空格

display:inline-block的元素之前的空行都刪除掉,如下寫法:

  1. 父元素font-size設定為0,這個直接看圖:

7.圖片要設定 width 和 height

如果頁面有使用img標籤,那麼img很建議設定widthheight。目的是為了在網速差或者其它原因載入不出圖片的時候,保證佈局不會亂。如下栗子,一個很普通的佈局。

但是萬一出現什麼情況,圖片載入不出來的話,建議的處理方式是第一種,顯示一張預設圖片,即使不顯示預設圖片,也讓圖片有一個佔位的作用,保證佈局不會亂!

如果圖片載入不出,img又沒有設定widthheight的話,就會像下面這樣,佈局亂了!

關於設定widthheight,我順便說幾點:

  1. PC 站,建議在img標籤的屬性設定widthheight。這樣避免載入不出 CSS 而錯位;
  2. 手機站,建議用 CSS 設定imgwidthheight,因為手機站要做適配,在屬性設定widthheight不靈活,比如使用rem佈局,在屬性那裡設定不了widthheight
  3. 如果圖片不固定,但是有一個max-widthmax-height,那麼建議在img的父元素設定widthheightimg根據父元素的widthheight設定max-widthmax-height

8.任意元素垂直居中

這裡只放圖,不解釋:

8-1. table-cell

8-2. flex

8-3. position,transform

8-4. position,margin

這個方式不推薦使用,因為這個寫法,.div2的寬高必須要設定,否則就是 100%,比如設定了top:0;bottom:0;效果和設定height:100%;是一樣的。如果想要避免,就必須要設定height

9.圖片預載入

這裡說的預載入,不是懶載入。首先根據我個人理解科普下,懶載入和預載入的區別。

  • 懶載入:頁面載入的時候,先載入一部分內容(一般是先載入首屏內容),其它內容等到需要載入的時候再進行載入。
  • 預載入:頁面載入的時候,先載入一部分內容(一般是先載入首屏內容),其它內容等到先載入的一部分內容(一般是首屏內容)載入完了,再進行載入。

兩種方式,都是為了減少使用者進入網站的時候,更快的看到首屏的內容。

下面栗子,將這#preloader這個元素加入到到 HTML 中,就可以實現通過 CSS 的background屬性將圖片預載入到螢幕外的背景上。只要這些圖片的路徑保持不變,當它們在 Web 頁面的其他地方被呼叫時,瀏覽器就會在渲染過程中使用預載入(快取)的圖片。簡單、高效,不需要任何 JavaScript。

1234567 #preloader {/*需要預載入的圖片*/background:url(image1.jpg)no-repeat,url(image2.jpg)no-repeat,url(image3.jpg)no-repeat;width:0px;height:0px;display:inline;}

但是這樣會有一個問題,因為#preloader預載入的圖片,會和頁面上的其他內容一起載入,增加了頁面的整體載入時間。所以需要用 JS 控制。

12345678910 functionpreloader(urlArr,obj){varbgText='';for(vari=0,len=urlArr.length;i<len;i++){bgText+='url('+urlArr[i]+') no-repeat,';}obj.style.background=bgText.substr(0,bgText.length-1);}window.onload=function(){preloader(['image1.jpg','image2.jpg','image3.jpg'],document.getElementById('preloader'));}

原理也很簡單,就是先讓首屏的圖片載入完,然後再載入其它的圖片。通過給#preloader設定背景圖片,載入所需要的圖片,然後頁面上需要載入這些圖片的時候,就直接從快取裡面拿圖片,不需要通過 HTTP 請求獲取圖片,這樣載入就很快。

10.慎用 * 萬用字元

在做網頁的時候,經常會使用下面兩種方式重置樣式,以此來消除標籤的預設佈局和不同瀏覽器對於同一個標籤的渲染。

1 *{margin0padding0;}

上面這種方式,程式碼少,但是效能差,因為渲染的時候,要匹配頁面上所有的元素。很多基礎樣式沒有marginpadding的元素,比如divli等都被匹配,完全沒必要。下面看另一種方式:

1 body,dl,dd,h1,h2,h3,h4,h5,h6,p,form,ol,ul{margin0padding0;}

這種方式,程式碼稍微多,但是效能比上面的方式好。在渲染的時候,只匹配body,dl,dd,h1,h2,h3,h4,h5,h6,p,form,ol,ul這裡面的元素,這些元素帶有marginpadding,需要重置。

再看例子:

1 .test *{color:red;}

匹配文件中所有的元素,然後分別向上逐級匹配classtest的元素,直到文件的根節點:

1 .testa{color:red;}

匹配文件中所有a的元素,然後分別向上逐級匹配classtest的元素,直到文件的根節點。

兩種方式,哪種更好不言而喻,所以在開發的時候,建議避免使用通配選擇器。

11.合併、壓縮 CSS

這個沒什麼好解釋的,就是壓縮和合並 CSS。

首先壓縮 CSS,除了使用工具,比如 Gulp、Webpack 等把程式碼壓縮,把空格和換行都去掉。還有一個建議就是屬性簡寫。

比如:

1234567891011 margin-top:0;margin-right:10px;margin-bottom:10px;margin-left:10px;background-image:url('test.jpg');background-position:top center;background-repeat:no-repeat;border-width:1px;border-style:solid;border-color:#000;color:#0099FF;

可以換成下面的:

1234 margin:010px10px10px;background:url('test.jpg')no-repeat top center;border:1pxsolid#000;color:#09F;      

至於合併的時候,我按照自己的開發習慣給幾個建議:

  1. 合併公用的樣式。比如專案的頭部、底部、側邊欄這些,一般都是公用的,這些可以寫在一個公用樣式表上,比如main.css
  2. 上面所說的main.css是每一個頁面都需要引入,而樣式重置表reset.css也是每一個頁面都需要用到的,那麼建議main.cssreset.css合併成一個檔案,給頁面引入,減少請求;
  3. 每個頁面對應的樣式為獨立的檔案。比如首頁對應的是index.css,產品列表頁對應的樣式是product-list.css。那麼index.css就只在首頁引入,其它頁面不引入,因為引入純屬浪費請求資源,其他頁面對應的樣式也是這個處理方式。index.cssproduct-list.css等其它頁面的樣式就保留單獨的檔案,不作合併處理。

12.CSS 在 head 引入

瀏覽器在所有的 stylesheets 載入完成之後,才會開始渲染整個頁面。在此之前,瀏覽器不會渲染頁面裡的任何內容,頁面會一直呈現空白。這也是為什麼要把 stylesheet 放在頭部的原因。如果放在 HTML 頁面底部,頁面渲染就不僅僅是在等待 stylesheet 的載入,還要等待 HTML 內容載入完成,這樣一來,使用者看到頁面的時間會更晚。

13.避免使用 @import

CSS 樣式檔案有兩種引入方式,一種是link元素,另一種是@import。在這裡,我建議就是避免使用@import。因為@import會影響瀏覽器的並行下載,使得頁面在載入時增加額外的延遲,增添了額外的往返耗時。而且多個@import可能會導致下載順序紊亂。

比如一個 CSS 檔案index.css包含了以下內容:@import url("reset.css")。那麼瀏覽器就必須先把index.css下載、解析和執行後,才下載、解析和執行第二個檔案reset.css。簡單的解決方法是使用替代@import

14.從 PSD 檔案思考怎麼寫程式碼

接到效果圖,先不用著急切圖,先看下 PSD 檔案。思考下怎麼排版,那些模組可以做成公用的模組,模組應該怎麼命名,寫樣式等。當我們拿到設計師給的 PSD 時,首先不要急於寫 CSS 程式碼,首先對整個頁面進行分析,先思考下面幾點:

  1. 分析頁面有哪些模組是公用的。常見公用模組有頭部、底部、選單欄、懸浮按鈕等;
  2. 分析模組有什麼樣式,把公用的樣式提取出來,公用樣式包括公用的狀態樣式。比如按鈕、輸入框、下拉框等公用的選中狀態,禁用狀態的樣式等。

15.小圖示的處理方案

一個網站肯定會有很多個小圖示,對於這些小圖示,目前的解決方案有兩個,CSS Sprite(雪碧圖),字型圖示,把圖片轉成 base64。下面對比一下這兩種方式:

  • CSS Sprite:把所有 icon 圖片合成一張 png 圖片,使用的是在對節點設定寬高,加上bacgroud-position。以背景圖方式顯展示需要的 icon,如果一個網站有 20 圖示,那麼就要請求 20 次。使用 CSS Sprite,只需要請求一次,大大的減少了 HTTP 請求。缺點就是管理不靈活,如果需要新增一個圖示,都需要改合併圖片的原始檔,圖示定位也要規範,不然容易干擾圖片之間的定位;
  • 字型圖示:簡單粗暴的理解就是把所有的圖示當成一個字型處理,這樣不用去請求圖片。一般是使用 class 來定義圖示,要替換圖示時,只需更換樣式名,管理方便,語意明確,靈活放大縮小,並且不會造成失真,但是隻支援單色的圖片。
  • base64:另一種方案就是把小的 icon 圖片轉成 base64 編碼,這樣可以不用去請求圖片,把 base64 編碼直接整合到 JS 或者 CSS 裡面,可以防止因為一些相對路徑,或者圖片被不小刪除了等問題導致圖片 404 錯誤。但是找個方式會生成一大串的 base64 編碼。一般來說,8K 以下的圖片才轉換成 base64 編碼。如果把一張 50K 的圖片轉成 base64 編碼,那麼會生成超過 65000 個字元的 base64 編碼,字元的大小就已經是將近 70K 了!建議就是:8K 以下的圖片才轉換成 base64 編碼。

16.不要在 ID 選擇器前面進行巢狀或寫標籤

  1. ID 在頁面上本來就是唯一的,而且人家權值那麼大,前方巢狀(.content #test)完全是浪費效能,以及多寫一些沒有意義的程式碼。這個雖然是一句話,但是還是有人犯這樣的錯。
  2. 除了巢狀,在 ID 的前面也不需要加標籤或者其它選擇器。比如div#test或者.test#test。這兩種方式完全是多餘的,理由就是 ID 在頁面就是唯一的。前面加任何東西都是多餘的!

17.把常用樣式抽封裝成公用樣式

把長段相同樣式提取出來作為公用樣式使用,比如常用的清除浮動,單行超出顯示省略號,多行超出省略號等。

如下栗子:

CSS
123456789101112131415 /*超出省略號*//*<p class='text-ellipsis'></p>*/.text-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}/*清除浮動*//*<div class='clearfix'></div>*/.clearfix:after {display:block;content:'';clear:both;height:0;}

18.CSS3 動畫的優化

在我之前一篇文章(移動 Web 開發問題和優化小結),也有寫過關於這個的優化建議,之前說的兩個建議是:

  1. CSS3 動畫或者過渡儘量使用transformopacity來實現動畫,不要使用lefttop
  2. 動畫和過渡能用CSS3解決的,就不要使用JS。如果是複雜的動畫可以使用CSS3+JS(或者HTML5+CSS3+JS)配合開發,效果只有想不到,沒有做不到。

下面補充一個:動畫不宜過多,尤其是手機網站,否則會出現效能的問題.比如 CPU 一下子就被佔用滿了,掉幀等。而且,不建議給每一個元素都使用硬體加速。

參考連結:

19.Body 設定最小寬度

這個是在 PC 站會出現的問題,應該大家都知道。下面簡單說一下!

比如下面的栗子,一個網站,頁面內容寬度是 1200px。看著很正常,沒什麼特別:

如果這個時候,把頁面視窗縮小。小於 1200px,頁面出現滾動條,然後把滾動條拖到最右邊:

這樣是不是就發現,頂部的圖片和背景有一部分是斷層了!解決這個問題也很簡單,就是給body加上min-width。值就是頁面寬度的值:body{min-width:1200px;}

重複上一步操作,無論怎麼改變瀏覽器視窗大小,都是正常的:

之所以會出現這樣的問題,是因為,比如視窗縮小到 900px 的時候,小於內容寬度的 1200px。就是出現橫向的滾動條,但是body的寬度是 900px。這個時候,如果有元素(比如圖片的灰色區域和粉紅色的圖片)是相對bodywidth設定 100%,那麼實際上這些元素的寬度也就是 900px。所以會出現斷層那些的視覺!解決方式就是給body加上min-width。讓body的寬度最小不會小於內容的寬度!

20.小結

關於我對 CSS 寫作建議和效能優化的一個總結,就到這裡了。CSS 絕對不是那種只要能用就行,或者只要能用 CSS 把佈局弄好就行的一門語言。CSS 給我的感覺,就是上手很簡單,但是如果想用好 CSS,還是得花時間去研究。CSS 或者 CSS3,能夠優化的東西還有很多,用好 CSS 或者 CSS3 能夠少寫很多 JS 程式碼,做出來的東西也是很神奇,大家還是得繼續學習當中的知識。

如果大家覺得我文章有哪個地方寫得不好,寫錯了,歡迎指正。如果有什麼其它的建議,歡迎指點,讓大家互相交流,互相學習,一起進步!最後,祝大家節日快樂!