CSS 優化、提高性能的方法有哪些?
堅決反對說 CSS 優化空間小、對性能影響小的答案。事實上大部分的複雜頁面都可以在完全不修改 JavaScript 代碼的情況下,通過 CSS 的優化大幅提升 render performance。
CSS 優化主要是四個方面:- 載入性能這個方面相關的 best practice 太多了,網上隨便找一找就是一堆資料,比如不要用 import 啊,壓縮啊等等,主要是從減少文件體積、減少阻塞載入、提高並發方面入手的,任何 hint 都逃不出這幾個大方向。
- 選擇器性能
可以參考 GitHub 的這個分享 https://speakerdeck.com/jonrohan/githubs-css-performance,但 selector 的對整體性能的影響可以忽略不計了,selector 的考察更多是規範化和可維護性、健壯性方面,很少有人在實際工作當中會把選擇器性能作為重點關注對象的,但也像 GitHub 這個分享裡面說的一樣——知道總比不知道好。
- 渲染性能渲染性能是 CSS 優化最重要的關注對象。頁面渲染 junky 過多?看看是不是大量使用了 text-shadow?是不是開了字體抗鋸齒?CSS 動畫怎麼實現的?合理利用 GPU 加速了嗎?什麼你用了 Flexible Box Model?有沒有測試換個 layout 策略對 render performance 的影響?這個方面搜索一下 CSS render performance 或者 CSS animation performance 也會有一堆一堆的資料可供參考。
- 可維護性、健壯性命名合理嗎?結構層次設計是否足夠健壯?對樣式進行抽象復用了嗎?優雅的 CSS 不僅僅會影響後期的維護成本,也會對載入性能等方面產生影響。這方面可以多找一些 OOCSS(不是說就要用 OOCSS,而是說多了解一下)等等不同 CSS Strategy 的信息,取長補短。
你可以關注一下CSS Lint (CSS Lint),這是一個發現CSS書寫問題,提升性能的工具,具體可以看這個文章:挪墨的空間 / 關注 CSS Lint
我複製規則過來:修復解析錯誤(Parsing errors should be fixed)
避免使用多類選擇符(Don"t use adjoining classes)IE6以及更古老的瀏覽器對類似.foo.bar的多類選擇符解析不正確,參考IE6下的多類選擇符一文。 移除空的css規則(Remove empty rules)這個規則不包含任何屬性,類似:.foo { }空規則的產生原因一般來說是為了預留樣式。去除這些空規則無疑能減少css文檔體積。正確使用display的屬性(Use correct properties for a display)由於display的作用,某些樣式組合會無效,徒增樣式體積的同時也影響解析性能。CSS Lint會檢查一下幾點: display:inline後不應該再使用width、height、margin、padding以及float。 display:inline-block後不應該再使用float。 display:block後不應該再使用vertical-align。 display:table-*後不應該再使用margin或者float。 不濫用浮動(Don"t use too many floats)雖然浮動不可避免,但不可否認很多css bug是由於浮動而引起。CSS Lint一旦檢測出樣式文件中有超過10次的浮動便會提示警告。 不濫用web字體(Don"t use too many web fonts)對於中文網站來說Web Fonts可能很陌生,國外卻很流行。web fonts通常體積龐大,而且一些瀏覽器在下載web fonts時會阻塞頁面渲染損傷性能。 不聲明過多的font-size(Don"t use too may font-size declarations)這是設計層面的問題,設計精良的頁面不會有過多的font-size聲明。 不在選擇符中使用ID標識符(Don"t use IDs in selectors)主要考慮到樣式重用性以及與頁面的耦合性。 不給h1~h6元素定義過多的樣式(Don"t qualify headings)
全站統一定義一遍heading元素即可,若需額外定製樣式,可使用其他選擇符作為代替。 不重複定義h1~h6元素(Heading styles should only be defined once)值為0時不需要任何單位(Zero values don"t need units)標準化各種瀏覽器前綴(Vendor prefixed properties should also have the standard)通常將瀏覽器前綴置於前面,將標準樣式屬性置於最後,類似: .foo {-moz-border-radius: 5px;border-radius: 5px; }使用CSS漸變等高級特性,需指定所有瀏覽器的前綴(CSS gradients require all browser prefixes)避免讓選擇符看起來像正則表達式(Avoid selectors that look like regular expressions)CSS3添加了一些類似~=等複雜屬性,也不是所有瀏覽器都支持,需謹慎使用。 遵守盒模型規則(Beware of broken box models)
上面回答已經很多很全了,我補充一點,就是看下需求有沒有簡化的可能,比如某一塊很酷炫的效果是否真的對用戶有必要?
比如一個內容列表,為了酷炫加上個 CSS3 transition 特效,反而讓用戶覺得不爽,非要等你這個動畫完了才能看內容。這個時候不寫代碼就是最高效的性能提升方法。
只有在非常複雜的頁面,樣式非常多的時候,CSS 的性能瓶頸才會凸顯出來,這時候更多要考慮的應該是有沒有必要做這麼複雜的頁面。【CSS代碼重構與優化之路】
寫CSS的同學們往往會體會到,隨著項目規模的增加,項目中的CSS代碼也會越來越多,如果沒有及時對CSS代碼進行維護,CSS代碼不斷會越來越多。CSS代碼交錯複雜,像一張龐大的蜘蛛網分布在網站的各個位置,你不知道修改這行代碼會有什麼影響,所以如果有修改或增加新功能時,開發人員往往不敢去刪除舊的冗餘代碼,而保險地增加新代碼,最終壞處就是項目中的CSS會越來越多,最終陷入無底洞。
CSS代碼重構的目的
我們寫CSS代碼時,不僅僅只是完成頁面設計的效果,還應該讓CSS代碼易於管理,維護。我們對CSS代碼重構主要有兩個目的:
1、提高代碼性能
2、提高代碼的可維護性
提高代碼性能
提高CSS代碼性能主要有兩個點:
1、提高頁面的載入性能
提高頁面的載入性能,簡單說就是減小CSS文件的大小,提高頁面的載入速度,盡可以的利用http緩存
2、提高CSS代碼性能
不同的CSS代碼,瀏覽器對其解析的速度也是不一樣的,如何提高瀏覽器解析CSS代碼的速度也是我們要考慮的
提高代碼的可維護性
提高CSS代碼可維護性主要是體現在下面幾點:
1、可重用性
一般來說,一個項目的整體設計風格是一致的,頁面中肯定有幾個風格一致但有些許不同的模塊,如何在儘可能多地重用CSS代碼,儘可能少地增加新代碼,這是CSS代碼中非常重要的一點。如果CSS代碼的重用性高,我們可能只需要寫一些不一樣的地方,對頁面性能和可維護性、提高開發效率都有很大的幫助。
2、可擴展性
如果產品增加了某個功能,我們應該保證新增加的CSS代碼不會影響到舊的CSS代碼和頁面,並且儘可能少地增加新代碼而重用舊代碼。
3、可修改性
如果某個模塊產品經理覺得要修改樣式,或者要刪掉它,如果沒有規劃好相應的CSS代碼,過了一段時間之後,開發人員可能已經不記得這段代碼作用了幾個地方,不敢修改或刪除它,這樣下去CSS代碼也就越來越多,影響了頁面的性能,還造成了代碼的複雜度。
CSS代碼重構的基本方法
前面說到CSS代碼重構的目的,現在來說一些如何達到這些目的的基本方法,這些方法都是易於理解,容易實施的一些手段,大家平時可能也不知不覺地在使用它。
提高CSS性能的手段
首先說說如何提高CSS性能,根據頁面的載入性能和CSS代碼性能,主要總結有下面幾點:
1、盡量將樣式寫在單獨的css文件裡面,在head元素中引用
有時候為了圖方便或者快速搞定功能,我們可能會直接將樣式寫在頁面的style標籤或者直接內聯在元素上,這樣雖然簡單方便,但是非常不利於日後的維護。將代碼寫成單獨的css文件有幾點好處:
(1)內容和樣式分離,易於管理和維護
(2)減少頁面體積
(3)css文件可以被緩存、重用,維護成本降低
2、不使用@import
這條手段已經是眾所周知,這裡簡單提一下,@import影響css文件的載入速度
3、避免使用複雜的選擇器,層級越少越好
有時候項目的模塊越來越多,功能越來越複雜,我們寫的CSS選擇器會內套多層,越來越複雜。
建議選擇器的嵌套最好不要超過三層,比如:
.header .logo .text{}
可以優化成
.haeder .logo-text{}
簡潔的選擇器不僅可以減少css文件大小,提高頁面的載入性能,瀏覽器解析時也會更加高效,也會提高開發人員的開發效率,降低了維護成本。
4、精簡頁面的樣式文件,去掉不用的樣式
很多時候,我們會把所有的樣式文件合併成一個文件,但是這樣有一個問題:很多其他頁面的CSS同時引用到當前頁面中,而當前頁面並沒有用到它們,這種情況會造成兩個問題:
(1)樣式文件偏大,影響載入速度
(2)瀏覽器會進行多餘的樣式匹配,影響渲染時間。
正確的處理方法是根據當前頁面需要的css去合併那些當前頁面用到的CSS文件。
PS:合併成一個文件有一個優點:樣式文件會被瀏覽器緩存,進入到其他頁面樣式文件不用再去下載。這條規則應根據場景來區別對待,如果是大項目,應該合併成不同的樣式文件,如果是簡單的項目,建議合併成一個文件即可。如果無法確認項目規模,建議分開成不同的樣式文件,日後要合併也比較方便。
5、利用CSS繼承減少代碼量
我們知道有一部分CSS代碼是可以繼承的,如果父元素已經設置了該樣式,子元素就不需要去設置該樣式,這個也是提高性能的行之有效的方法。
常見的可以繼承的屬性比如:
color,font-size,font-family等等
不可繼承的比如:
position,display,float等
提高可維護性的方法
提高CSS代碼的可維護性,簡單說就是要讓開發人員易於理解CSS代碼,容易去修改它,不會破壞原有功能。下面說說一些常用手段。
1、命名與備註
命名是提高代碼可讀性的第一步,也是及其重要的一步。很多人都有這樣的體會:命名是寫代碼中最讓程序員頭疼的事情之一,尤其是對母語非英語的開發人員來說,要找一個合適貼切的名字並不容易。提高自己命名的能力,可以多看看別人的代碼。下面是CSS中的一些命名相關的建議:
頭:header
內容:content/container
尾:footer
導航:nav
側欄:sidebar
欄目:column
頁面外圍控制整體佈局寬度:wrapper
左右中:left right center
登錄條:loginbar
標誌:logo
廣告:banner
頁面主體:main
熱點:hot
新聞:news
下載:download
子導航:subnav
菜單:menu
子菜單:submenu
搜索:search
友情鏈接:friendlink
頁腳:footer
版權:copyright
滾動:scroll
內容:content
標籤:tags
文章列表:list
提示信息:msg
小技巧:tips
欄目標題:title
加入:joinus
指南:guide
服務:service
註冊:regsiter
狀態:status
投票:vote
合作夥伴:partner
導航:nav
主導航:mainnav
子導航:subnav
頂導航:topnav
邊導航:sidebar
左導航:leftsidebar
右導航:rightsidebar
菜單:menu
子菜單:submenu
標題: title
摘要: summary
2、提取重複樣式
這一個方法很容易理解,簡單說就是提取相同的樣式成為一個單獨的類再引用,這樣不僅可以精簡CSS文件大小,而且CSS代碼變少,更易於重用和維護。例如下面的例子:
原來的代碼是這樣:
.about-title{
margin: 0 auto 6rem; color: #333; text-align: center; letter-spacing: 4px;
font-size: 2rem;}
.achieve-title{
margin: 0 auto 6rem; color: #fff; text-align: center; letter-spacing: 4px;
font-size: 2rem;}
這兩個樣式的區別在於文字顏色的不同,我們可以將其公共的樣式提取出來,然後再分別設置其不同的樣式
.column-title{
margin: 0 auto 6rem; text-align: center; letter-spacing: 4px; font-size:
2rem;}
.about{
color: #333;
}
.achieve{
color:#fff;
}
提取公用的部分,然後在頁面上分別引用column-title和about等,這樣代碼更簡潔,維護起來也更方便了。這個例子非常簡單,實際上項目中可能有更複雜的情況,總之就要要儘可能的DRY,儘可能的提取重複的東西。
3、書寫順序
這個書寫順序指的是各個樣式的書寫順序,下面是推薦的CSS書寫順序
(1)位置屬性(position, top, right, z-index, display, float等)
(2)大小(width, height, padding, margin)
(3)文字系列(font, line-height, letter-spacing, color- text-align等)
(4)背景(background, border等)
(5)其他(animation, transition等)
書寫順序不一定非得按照上面的推薦來進行,而是根據你自己的習慣,但是最好能保證前後的習慣一致的,或者團隊應該有一個共同的代碼規範去遵守,這樣後期維護起來也會方便許多。
以上是我個人總結的一些簡單的寫好和重構CSS代碼的方法,大家當然不必拘泥於此,有不同的意見和建議歡迎進行交流!
CSS方法論
什麼是CSS方法論呢?簡單地說就是一些同行為了提高CSS可維護性、提出的一些編寫CSS代碼的規範和方法。他們提出了一些概念,這些概念可能聽起來很高大上,但是實際你平時可能不知不覺也會用到這些所謂的CSS方法論。下面我簡單地介紹下幾個比較常見的CSS方法論。
OOCSS
OOCSS是(Object Oriented CSS),顧名思義就是面向對象的CSS。
OOCSS主要有兩個原則:
1、結構和樣式分離
我們平時一定遇到過這種情況,比如一個頁面存在著多個不同功能的按鈕,這些按鈕的形狀大小都差不多,但是根據不同的功能會有不同的顏色或背景來加以區分。如果不進行結構和樣式分離,我們的CSS代碼可能是這樣的
.btn-primary{
width:100px;
height:50px;
padding:5px 3px;
background:#ccc;
color:#000;
}
.btn-delete{
width:100px;
height:50px;
padding:5px 3px;
background:red;
color:#fff;
}
這兩個或者可能更多的按鈕擁有一些不同的樣式,但是它們同時擁有相同的大小樣式等,我們將其抽象的部分提取出來,結果如下:
.btn{
width:100px;
height:50px;
padding:5px
3px;}
.primary{
background:red;
color:#fff;
}
.delete{
background:red;
color:#fff;
}
這樣提取公用的樣式出來,然後按鈕同時引用btn和primary等。這種做法除了減少重複的代碼精簡CSS之外,還有一個好處是復用性,如果需要增加其他額外的按鈕,只需要編寫不同的樣式,和btn配合使用即可。
(2)容器和內容分離
我們平時寫代碼一定寫過這樣代碼
.content h3{
font-size:20px;
color:#333;
}
這樣的代碼就是內容依賴於容器,沒有分離的代碼,也就是說h3的樣式依賴於.content容器,如果其他地方要用到相同的樣式,但是它的容器卻不是.content,那你可能就是要再寫一遍.something
h3。
所以OOCSS推薦分離容器和內容,可以修改成:
.title{
font-size:20px;
color:#333;
}
關於這一點,我個人建議要分情況來看,像前面這個例子,它適合樣式和容器分離。但是比如下面這種情況:
.menu li{
font-size:12px;
}
這種ul,li列表的樣式,我覺的就按照我們原先的做法就可以,不一定非得給一個類給li來設定樣式,即
.menu-item{
font-size:12px;
}
這樣頁面的li標籤需要引用menu-item類。
當然採用哪一種方式更好我也不卻確定,我自己比較喜歡.menu li的寫法,大家自行思考。
這就是OOCSS的兩個基本原則,這裡只是簡單介紹OOCSS,各位如果有興趣的話請自行Google查找相關資料。
SMACSS
SMACSS是什麼呢,它的全稱是Scalable and Modular Architecture for
CSS。簡單說就是可擴展和模塊化的CSS架構。
SMACSS將樣式分成5種類型:Base,Layout,Module,State,Theme,我們簡單來說說每一種類型分別指什麼。
1、Base
基礎樣式表,定義了基本的樣式,我們平時寫CSS比如reset.css就是屬於基礎樣式表,另外我認為清除浮動,一些動畫也可以歸類為基礎樣式。
2、Layout
布局樣式,用於實現網頁的基本布局,搭起整個網頁的基本骨架。
3、Module
網頁中不同的區域有這個不同的功能,這些功能是相對獨立的,我們可以稱其為模塊。模塊是獨立的,可重用的組件,它們不依賴於布局組件,可以安全的刪除修改而不影響其他模塊。
4、State
狀態樣式,通常和js一起配合使用,表示某個組件或功能不同的狀態,比如菜單選中狀態,按鈕不可用狀態等。
關於狀態樣式,我個人覺得要分情況進行討論:
(1)不同組件的同一狀態的樣式是一樣的,比如頭部的導航菜單的選中狀態樣式和側欄的菜單選中狀態樣式是一樣的,我認為這部分狀態樣式可以歸類為State
(2)不同組件的統一狀態的樣式是不一樣的,即兩個地方的菜單雖然都是選中狀態,但是他們卻又不同的選中樣式,這部分樣式不應該被認為是State類型,而是應該放在其組件對應的Module中。
5、Theme
皮膚樣式,對於可更換皮膚的站點來說,這個是很有必要的,分離了結構和皮膚,根據不同的皮膚應用不同的樣式文件。
BEM
BEM是Block,Element,Modifier的縮寫。下面分別來介紹一下這三個概念:
(1)Block:在BEM的理論中,一個網頁是由block組成的,比如頭部是個block,內容是block,logo也是block,一個block可能由幾個子block組成。
(2)Element:element是block的一部分,具有某種功能,element依賴於block,比如在logo中,img是logo的一個element,在菜單中,菜單項是菜單的一個element
(3)Modifier:modifier是用來修飾block或者element的,它表示block或者element在外觀或行為上的改變
我們通過BEM命名法寫樣式如下:
.block{}
.block-element{}
.block-modifier{}
.block-element-modifier{}
BEM將頁面解析為block和element,然後根據不同的狀態使用modifier來設置樣式。
我對BEM的思想理解可能不到位,對BEM的看法主要是由兩點:
(1)頁面CSS模塊化,每個block就是一個模塊,模塊間相互獨立
(2)多級的class命名,避免選擇器的嵌套結構
關於CSS方法論
上面提到的這些CSS方法論,大家看了就會發現,它們其實有很多思想是相同的,比如:
1、選擇器的嵌套的優化
2、CSS代碼模塊化
3、抽象CSS代碼
…
這些方法論,我們學習的時候,最重要的是去理解其思想,不一定非得照搬它的實現形式,多種方法結合使用。
我自己總結的方法
談了這麼多,下面來說說我自己總結的寫CSS代碼的一些關鍵點。
1、寫代碼之前:從PSD文件出發
當我們拿到設計師給的PSD時,首先不要急於寫CSS代碼,首先對整個頁面進行分析,主要關注點是下面幾個:
(1)頁面分成了幾個模塊,哪些模塊是公用的,常見的比如頭部和底部,還有一些菜單欄等等
(2)分析每一個模塊都有什麼樣式,提取出公用的樣式,注意公用樣式是全局公用(整個頁面公用)還是局部公用(模塊內公用),公用樣式包括公用的狀態樣式,比如公用的選中狀態,禁用狀態等等。
2、開始寫代碼
根據對PSD文件的分析,我們就可以開始著手寫代碼,我比較推薦SMACSS將樣式分成不同類型的做法:
(1)第一步是搭好頁面的骨架,也就是base樣式,layout樣式。
(2)第二步就是依次實現不同的模塊,在這裡我推薦BEM的命名思想,但是可以嵌套一到兩層的選擇器結構
3、優化代碼
我相信當我們完成基本的頁面效果後,還是會存在著一些重複的或者不夠簡潔的代碼,這時候就是要去優化這些代碼,主要是在提取重複代碼,儘可能地精簡代碼。
更多好文章:
http://weixin.qq.com/r/azrB2YbE6NuXrcK69295 (二維碼自動識別)
css tree-shaking 可以檢測去除無用的css
linxi:Tree-Shaking性能優化實踐 - 實踐篇zhuanlan.zhihu.comcss性能優化的地方很多,結合以上幾位大神的回答,總結如下:1.慎重使用高性能屬性:浮動、定位;2.盡量減少頁面重排、重繪 重排按照css的書寫順序: 位置:positon、top、left、z-index、float、dispay 大小:width、height、margin、padding 文字系列: font、line-height、color、letter-spacing 背景邊框:background、 border 其它:anmation、transition 重繪:border、outline、background、box-shadow,能使用background-color,就盡量不要使用background;3.去除空規則:{};4.屬性值為0時,不加單位;5.屬性值為浮動小數0.**,可以省略小數點之前的0;6.標準化各種瀏覽器前綴:帶瀏覽器前綴的在前。標準屬性在後;7.不使用@import前綴,它會影響css的載入速度;8.充分利用css繼承屬性,減少代碼量;9.抽象提取公共樣式,減少代碼量;10.選擇器優化嵌套,盡量避免層級過深;11.css雪碧圖,同一頁面相近部分的小圖標,方便使用,減少頁面的請求次數,但是同時圖片本身會變大,使用時,優劣考慮清楚,再使用;12.將css文件放在頁面最上面
這裡面有:http://ued.alimama.com/front-end/quick-tips-among-yahoo-n-rules/簡單總結和css有關的:
- 盡量減少HTTP請求個數——須權衡
- 一般就是把多個css用merge(後台)合併
CSS本身影響性能的非常少,除了expression這個本身不符合規範的特性,CSS選擇器對效率的影響基本微乎其微。影響CSS性能的特性主要是一些CSS3的特性,複雜頁面的大布局使用flex布局,列表每項使用shadow、漸變、變形等,CSS動畫,...
非常詳細的解釋: https://segmentfault.com/a/1190000000490328
reflow和repaint都是耗費瀏覽器性能的操作,這兩者尤以reflow為甚;因為每次reflow,瀏覽器都要重新計算每個元素的形狀和位置。由於reflow和repaint都是非常消耗性能的,我們的瀏覽器為此做了一些優化。瀏覽器會將reflow和repaint的操作積攢一批,然後做一次reflow。但是有些時候,你的代碼會強制瀏覽器做多次reflow。 【看薦黑板報】
感覺跟電腦配置也有關係O(∩_∩)O哈哈~
css 文件大小(重用/繼承/組合等等); css 選擇器效率;
推薦閱讀:
※前端組件化普及的今天花時間鑽研bootstrap3/AdminLTE2這些UI框架還能有多大收益?
※bootstrap中有瀑布流的組件嗎?
※Bootstrap 4 大家有什麼看法?我想知道有什麼新的變化?有什麼新功能添加?