Web優化的對象包括頁面性能、用戶體驗、開發效率、代碼優化、網絡延遲等,本系列會列舉出眾多常用的優化技巧,每個技巧都可深入分析,在此只做拋磚引玉。
  本系列優化內容提煉于《[前端面試寶典]([https://book.douban.com/subject/30324146/](https://book.douban.com/subject/30324146/))》、《[高效前端](https://book.douban.com/subject/30170670/)》、《[高性能JavaScript](https://book.douban.com/subject/5362856/)》、《[CSS重構](https://book.douban.com/subject/27179964/)》等書籍,以及《[2020前端性能優化清單](https://cloud.tencent.com/developer/article/1621632)》等網絡資源。
  CSS優化包括減少樣式量、合理使用CSS3特性、對樣式分類、采用預處理器等。
## 一、CSS選擇器
**1)匹配優化**
  由于CSS選擇器是從右往左進行匹配,因此下面的這條規則并不高效,瀏覽器需要遍歷頁面中的div元素并確定其父元素的id是否為“container”。
~~~css
#container > div { }
~~~
  最右邊的參數叫關鍵選擇器,對瀏覽器執行的工作量起主要影響。在優化時,可將重心放到關鍵選擇器上。
**2)保持簡潔**
  雖然下面的選擇器非常精確,但是一旦HTML結構發生變化,匹配就會失敗。
~~~css
div > nav > ul > li > a { }
~~~
  更佳的做法是為HTML元素增加一個類,并為該類增加樣式。簡潔的選擇器也會讓CSS文件變小。
~~~css
.nav-link { }
~~~
**3)語義化類名**
  有意義的類名可提供恰如其分的樣式信息,既能防止因細節過少而表意模糊,又能避免因信息過多而妨礙代碼重用,例如用“.animal”描述動物的樣式。
  注意,也不要過于精確,例如female-black-and-white-kitten(雌性—黑—和—白—小貓)。
**4)避免相同類名**
  有時候會故意寫相同類名,以覆蓋之前的樣式。但在多人協作時,很容易因為同名而發生沖突,可以引入一個命名空間加以區分。
**5)偽類的妙用**
  偽類不僅僅只是鏈接的懸浮、元素位置,CSS3新增了一大批[偽類](http://www.hmoore.net/pwstrick/fe-questions/1627439),既彌補了常規選擇器的不同,也能解決部分頁面交互。
  例如自定義單選框的選中樣式,以往得借助JavaScript,現在只需幾句CSS就可完成。如下所示,為單選框聲明:checked偽類,
~~~css
.ui-radio span {
display: block;
width: 100%;
background: #FFF;
color: #F60;
}
.ui-radio input[type=radio]:checked ~ span {
background: #Fc0;
color: #FFF;
}
~~~
## 二、CSS屬性
**1)巧用繼承**
  屬性繼承可以通過inherit關鍵字顯式聲明,而有些屬性還支持自動繼承,常用的包括:
1. 字體系列屬性:font-family,font-size
2. 文本系列屬性:text-indent,line-height,color
3. 元素可見性:visibility
4. 表格布局屬性:border-style
5. 列表布局屬性:list-style,list-style-type
6. 光標屬性:cursor
  布局相關的屬性大都不可繼承。樣式多繼承可以減少很多冗余代碼,減小CSS文件的大小,保持高可讀性,降低后期維護成本。
**2)慎用!important**
  聲明!important后的屬性,其特殊性非常高,很容易影響別處的樣式,并且在老舊項目中很難修改,會出現牽一發動全身的情況。
**3)flexbox**
  [彈性布局](https://www.cnblogs.com/strick/p/5204082.html)很適合移動端頁面,大大簡化了頁面布局難度,并且已經獲得了瀏覽器的廣泛支持。
  過去布局常會用[float屬性](http://www.hmoore.net/pwstrick/fe-questions/1627441),但其實它最初的作用是為了實現文字環繞圖像的效果。當用于布局時,必須清除浮動,否則會造成父元素塌陷、非浮動元素環繞等問題。
  所以要避免使用float屬性,多用彈性布局。CSS3最新的[網格布局](http://www.hmoore.net/pwstrick/fe-questions/1627446)比彈性布局更加強大,給出了許多優秀的布局解決方案。
**4)屬性簡寫**
  使用屬性簡寫,可以避免冗長的屬性聲明。當在大型樣式表中持續使用時,節省的空間將會很可觀。
~~~css
.container {
background-color: #FC0;
background-image: url(lake.png);
background-repeat: no-repeat;
/* 簡寫 */
background: #FC0 url(lake.png) no-repeat;
}
~~~
  還有一種簡寫,可用短的屬性描述相同的功能,例如當只需要聲明background-color屬性,可用background替代。
~~~css
.container {
background-color: #FC0;
/* 簡寫 */
background: #FC0;
}
~~~
**4)減少冗余**
  將選擇器之間重復的屬性提取到一起,通過最小化屬性聲明的次數,來減少代碼膨脹。
~~~css
.main,
.side {
margin: 20px;
color: #F60;
}
~~~
**5)偽元素**
  偽元素可簡化頁面的HTML結構,例如可用它來畫那些無關緊要的分隔線,或用偽元素清除浮動、增加計數器等。
**6)CSS3屬性**
  CSS3提供了許多新屬性,可用來替換JavaScript或圖像。
  例如CSS3的border-radius屬性和border-shadow屬性,可以不用再借助圖像實現圓角和陰影,不僅減少了與服務器之間的通信,還加快了開發速度。
  再例如CSS3提供了[濾鏡](http://www.hmoore.net/pwstrick/fe-questions/1627443)(filter)功能,不必再借助Canvas來實現濾鏡的功能。還有linear-gradient()函數用于繪制[漸變](http://www.hmoore.net/pwstrick/fe-questions/1627442)。
**7)動畫**
  很多動畫現在可以由CSS3屬性(animation和transition)實現,不必再借助JavaScript,減少了JavaScript的權重。由于瀏覽器對CSS3的原生支持,因此動畫也變得更加流暢。
  animation常與transform結合,進行多層繪制,避免觸發影響渲染性能的重排和重繪。例如使用一個3D transform屬性將元素提升至合成層,進行GPU圖形處理加速。
~~~css
.move {
transform: translate3d(0,0,0);
}
~~~
**8)will-change**
  will-change屬性會告知瀏覽器該元素會有哪些變化,讓瀏覽器在元素屬性真正發生變化之前提前做好對應的優化準備工作。
  例如將一部分復雜的計算工作提前準備好,加快頁面反應速度。
## 三、代碼組織
**1)請求和位置**
  用link元素加載CSS可實現并行請求,并且將CSS文件放置在head中盡早加載,防止無樣式的內容閃爍,加快初始頁面加載時的渲染速度。
**2)減少base64**
  有時候會將一些小圖標轉換成base64內嵌到CSS文件中,雖然這樣減少了通信,但是會讓CSS文件極速膨脹,需要做適當地權衡。
**3)內聯樣式**
  如果CSS文件的內容很少,那么可以直接將其內聯到HTML結構中。雖然對緩存不利,但對首次加載有很大的作用。
**4)僵尸代碼**
  僵尸代碼是指存在但沒有使用的代碼,需要將它們刪除。CSS中的僵尸代碼具體表現為:沒有使用的聲明塊、重復的聲明塊和聲明語句。
**5)分類**
  按照樣式產生作用的順序組織CSS代碼。
1. 通用樣式,用來設定基準,以消除不同瀏覽器之間的不一致性。
2. 基礎樣式,為網站的所有元素提供基本的樣式,例如留白(margin和padding)、字體、顏色等。
3. 組件樣式,添加了樣式的元素或元素組合,例如進度條、彈框等。
4. 結構化樣式,用來創建網頁的布局,常用于定義尺寸。
5. 功能性樣式,所有樣式中最精確的樣式,為滿足單一目的而實現的樣式。
6. 瀏覽器特定樣式,只對特定的瀏覽器生效,通常不夠優雅。
**6)關鍵CSS**
  關鍵CSS是用戶會立即看到的內容樣式(即首屏樣式),需要盡快加載。可將首屏樣式提取到單獨的文件中,或用工具將這些樣式內嵌到style元素中。
  對于首屏以外的樣式,可通過preload加載,使其不阻塞渲染,如下所示,使用as來指定將要預加載的內容類型。
~~~html
<link rel="preload" href="style.css" as="style">
~~~
**7)CSS預處理器**
  CSS預處理器包括SASS和LESS,它們能為CSS提供了變量、函數、語句等編程特性,并引入了CSS模塊化的功能。即使項目規模擴大,也能處理的游刃有余。
**8)方法論**
  [CSS方法論](http://www.hmoore.net/pwstrick/fe-questions/1627447)是一種面向CSS、由個人和組織設計、已被諸多項目檢驗且公認有效的最佳實踐。
  這些方法論都會涉及結構化的命名約定,并且在組織CSS時可提供相應的指南,從而提升代碼的性能、可讀性以及可維護性。
  目前比較流行的三種CSS方法論:OOCSS、BEM和SMACSS。
*****
> 原文出處:
[博客園-Web優化躬行記](https://www.cnblogs.com/strick/category/1795726.html)
[知乎專欄-Web優化躬行記](https://zhuanlan.zhihu.com/c_1260996761008627712)
已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎閱讀。

推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
- ES6
- 1、let和const
- 2、擴展運算符和剩余參數
- 3、解構
- 4、模板字面量
- 5、對象字面量的擴展
- 6、Symbol
- 7、代碼模塊化
- 8、數字
- 9、字符串
- 10、正則表達式
- 11、對象
- 12、數組
- 13、類型化數組
- 14、函數
- 15、箭頭函數和尾調用優化
- 16、Set
- 17、Map
- 18、迭代器
- 19、生成器
- 20、類
- 21、類的繼承
- 22、Promise
- 23、Promise的靜態方法和應用
- 24、代理和反射
- HTML
- 1、SVG
- 2、WebRTC基礎實踐
- 3、WebRTC視頻通話
- 4、Web音視頻基礎
- CSS進階
- 1、CSS基礎拾遺
- 2、偽類和偽元素
- 3、CSS屬性拾遺
- 4、浮動形狀
- 5、漸變
- 6、濾鏡
- 7、合成
- 8、裁剪和遮罩
- 9、網格布局
- 10、CSS方法論
- 11、管理后臺響應式改造
- React
- 1、函數式編程
- 2、JSX
- 3、組件
- 4、生命周期
- 5、React和DOM
- 6、事件
- 7、表單
- 8、樣式
- 9、組件通信
- 10、高階組件
- 11、Redux基礎
- 12、Redux中間件
- 13、React Router
- 14、測試框架
- 15、React Hooks
- 16、React源碼分析
- 利器
- 1、npm
- 2、Babel
- 3、webpack基礎
- 4、webpack進階
- 5、Git
- 6、Fiddler
- 7、自制腳手架
- 8、VSCode插件研發
- 9、WebView中的頁面調試方法
- Vue.js
- 1、數據綁定
- 2、指令
- 3、樣式和表單
- 4、組件
- 5、組件通信
- 6、內容分發
- 7、渲染函數和JSX
- 8、Vue Router
- 9、Vuex
- TypeScript
- 1、數據類型
- 2、接口
- 3、類
- 4、泛型
- 5、類型兼容性
- 6、高級類型
- 7、命名空間
- 8、裝飾器
- Node.js
- 1、Buffer、流和EventEmitter
- 2、文件系統和網絡
- 3、命令行工具
- 4、自建前端監控系統
- 5、定時任務的調試
- 6、自制短鏈系統
- 7、定時任務的進化史
- 8、通用接口
- 9、微前端實踐
- 10、接口日志查詢
- 11、E2E測試
- 12、BFF
- 13、MySQL歸檔
- 14、壓力測試
- 15、活動規則引擎
- 16、活動配置化
- 17、UmiJS版本升級
- 18、半吊子的可視化搭建系統
- 19、KOA源碼分析(上)
- 20、KOA源碼分析(下)
- 21、花10分鐘入門Node.js
- 22、Node環境升級日志
- 23、Worker threads
- 24、低代碼
- 25、Web自動化測試
- 26、接口攔截和頁面回放實驗
- 27、接口管理
- 28、Cypress自動化測試實踐
- 29、基于Electron的開播助手
- Node.js精進
- 1、模塊化
- 2、異步編程
- 3、流
- 4、事件觸發器
- 5、HTTP
- 6、文件
- 7、日志
- 8、錯誤處理
- 9、性能監控(上)
- 10、性能監控(下)
- 11、Socket.IO
- 12、ElasticSearch
- 監控系統
- 1、SDK
- 2、存儲和分析
- 3、性能監控
- 4、內存泄漏
- 5、小程序
- 6、較長的白屏時間
- 7、頁面奔潰
- 8、shin-monitor源碼分析
- 前端性能精進
- 1、優化方法論之測量
- 2、優化方法論之分析
- 3、瀏覽器之圖像
- 4、瀏覽器之呈現
- 5、瀏覽器之JavaScript
- 6、網絡
- 7、構建
- 前端體驗優化
- 1、概述
- 2、基建
- 3、后端
- 4、數據
- 5、后臺
- Web優化
- 1、CSS優化
- 2、JavaScript優化
- 3、圖像和網絡
- 4、用戶體驗和工具
- 5、網站優化
- 6、優化閉環實踐
- 數據結構與算法
- 1、鏈表
- 2、棧、隊列、散列表和位運算
- 3、二叉樹
- 4、二分查找
- 5、回溯算法
- 6、貪心算法
- 7、分治算法
- 8、動態規劃
- 程序員之路
- 大學
- 2011年
- 2012年
- 2013年
- 2014年
- 項目反思
- 前端基礎學習分享
- 2015年
- 再一次項目反思
- 然并卵
- PC網站CSS分享
- 2016年
- 制造自己的榫卯
- PrimusUI
- 2017年
- 工匠精神
- 2018年
- 2019年
- 前端學習之路分享
- 2020年
- 2021年
- 2022年
- 2023年
- 2024年
- 日志
- 2020