To define is to limit.
定義一樣?xùn)|西,就意味著限制了它。愛(ài)掏網(wǎng) - it200.com——王爾德 《道林·格雷的畫(huà)像》
前言
這里主要總結(jié)一下CSS是怎么一步步演化呈現(xiàn)在百花齊放的局面,從用上React之后就更加多選擇了,我就舉例一下我的理解和用過(guò)的方案,還有一些了解過(guò)覺(jué)得還不錯(cuò)的方案.本身沒(méi)有推薦或貶低哪些的意思,只是覺(jué)得可以滿足需求的都是可以使用的方案.
CSS
用官方口吻來(lái)說(shuō)就是
CSS 能夠?qū)W(wǎng)頁(yè)中元素位置的排版進(jìn)行像素級(jí)精確控制,支持幾乎所有的字體字號(hào)樣式,擁有對(duì)網(wǎng)頁(yè)對(duì)象和模型樣式編輯的能力。愛(ài)掏網(wǎng) - it200.com
具有以下特點(diǎn):
- 豐富的樣式定義
CSS提供了豐富的包括但不限于樣式外觀,文本字體,背景屬性,邊距形狀等等的能力,還有一些瀏覽器特有的屬性定制.
- 易于使用修改
可以將樣式定義在HTML元素的style屬性中,HTML文檔的header部分,也可以將樣式聲明在一個(gè)專門(mén)的CSS文件中。愛(ài)掏網(wǎng) - it200.com
可以將相同樣式的元素進(jìn)行歸類使用同一個(gè)樣式進(jìn)行定義,也可以將某個(gè)樣式應(yīng)用到所有同名的HTML標(biāo)簽中。愛(ài)掏網(wǎng) - it200.com
- 多頁(yè)面應(yīng)用
CSS樣式表理論上不屬于任何頁(yè)面文件,在任何頁(yè)面文件中都可以將其引用。愛(ài)掏網(wǎng) - it200.com這樣就可以實(shí)現(xiàn)多個(gè)頁(yè)面風(fēng)格的統(tǒng)一。愛(ài)掏網(wǎng) - it200.com
- 層疊
簡(jiǎn)單的說(shuō),層疊就是對(duì)一個(gè)元素多次設(shè)置同一個(gè)樣式,后來(lái)定義的樣式將對(duì)前面的樣式設(shè)置進(jìn)行重寫(xiě)。愛(ài)掏網(wǎng) - it200.com
- 體積減少
在使用HTML定義頁(yè)面效果的網(wǎng)站中,往往需要大量或重復(fù)的表格和font元素形成各種規(guī)格的文字樣式,而將樣式的聲明單獨(dú)放到CSS樣式表中,可以大大的減小頁(yè)面的體積,這樣在加載頁(yè)面時(shí)使用的時(shí)間也會(huì)大大的減少。愛(ài)掏網(wǎng) - it200.com另外,CSS樣式表的復(fù)用更大程序的縮減了頁(yè)面的體積,減少下載的時(shí)間。愛(ài)掏網(wǎng) - it200.com
然后隨著用戶審美水平日益提高的標(biāo)準(zhǔn)和需求,普通的樣式已經(jīng)不足以支撐起來(lái)了,特別有些簡(jiǎn)單要求還會(huì)讓開(kāi)發(fā)絞盡腦汁用盡各種奇淫巧技來(lái)實(shí)現(xiàn),這種情況甚至?xí)蟠筮`背結(jié)構(gòu)和樣式分離的原則.
CSS3
作為CSS的升級(jí)版,主要包括盒子模型、列表模塊、超鏈接方式、語(yǔ)言模塊、背景和邊框、文字特效、多欄布局等模塊.
CSS3規(guī)范的一個(gè)新特點(diǎn)是被分為若干個(gè)相互獨(dú)立的模塊。愛(ài)掏網(wǎng) - it200.com一方面分成若干較小的模塊較利于規(guī)范及時(shí)更新和發(fā)布,及時(shí)調(diào)整模塊的內(nèi)容,這些模塊獨(dú)立實(shí)現(xiàn)和發(fā)布,也為日后CSS的擴(kuò)展奠定了基礎(chǔ)。愛(ài)掏網(wǎng) - it200.com另外一方面,由于受支持設(shè)備和瀏覽器廠商的限制,沒(méi)備或者廠商可以有選擇的支持一部分模塊,支持CSS3的一個(gè)子集,這樣有利于CSS3的推廣,但不同瀏覽器在不同時(shí)段支持不同特性,這也讓跨瀏覽器開(kāi)發(fā)變得復(fù)雜,當(dāng)然截止到2024,主流瀏覽器已經(jīng)基本支持了.低端版本也能通過(guò)各種輔助插件完成.
提升優(yōu)勢(shì):
- 減少開(kāi)發(fā)成本與維護(hù)成本
例如以前需要使用圖片定位模擬圓角,絕對(duì)定位+定時(shí)器模擬動(dòng)畫(huà),元素偽造滾動(dòng)條樣式等各種繁瑣工作都可以省略掉了.
- 提高頁(yè)面性能
減少多余的標(biāo)簽嵌套以及圖片的使用數(shù)量,意味著用戶要下載的內(nèi)容將會(huì)更少,頁(yè)面加載也會(huì)更快,能夠減少用戶訪問(wèn)Web站點(diǎn)時(shí)的HTTP請(qǐng)求數(shù),這是提升頁(yè)面加載速度的最佳方法之一
CSS3的推廣一方面增強(qiáng)了樣式的展示,一方面免去開(kāi)發(fā)實(shí)現(xiàn)的額外工程,但是本質(zhì)上并沒(méi)有減少開(kāi)發(fā)的工作量,因?yàn)橛泻芏囝愃贫幌嗤臉邮竭€是需要手寫(xiě)出來(lái).現(xiàn)在的網(wǎng)頁(yè)越來(lái)越大,畫(huà)面越來(lái)越豐富,于是就應(yīng)運(yùn)而生出了------
預(yù)處理器
因?yàn)槲叶际鞘褂肧CSS,就以此舉例,但是其實(shí)語(yǔ)法和實(shí)現(xiàn)功能大致相同的.
預(yù)處理器是一種強(qiáng)化 CSS 的輔助工具,它在 CSS 語(yǔ)法的基礎(chǔ)上增加了變量 (variables)、嵌套 (nested rules)、混合 (mixins)、導(dǎo)入 (inline imports)
等高級(jí)功能,這些拓展令 CSS 更加強(qiáng)大與優(yōu)雅,有助于更好地組織管理樣式文件,以及更高效地開(kāi)發(fā)項(xiàng)目.
簡(jiǎn)單舉例常用而強(qiáng)大的特性:
- 嵌套規(guī)則 (Nested Rules)
允許將一套 CSS 樣式嵌套進(jìn)另一套樣式中,內(nèi)層的樣式將它外層的選擇器作為父選擇器,還有屬性嵌套,占位符選擇器等等
- SassScript
可以通過(guò)聲明變量,函數(shù),運(yùn)算等抽取重復(fù)樣式代碼減少大量重復(fù)樣板代碼.
- 指令
@import
導(dǎo)入 SCSS 或 Sass 文件 ,@media
嵌套在 CSS 規(guī)則內(nèi),@extend
繼承樣式等 - 控制指令
運(yùn)用各種判斷循環(huán)實(shí)現(xiàn)控制樣式
CSS的瓶頸
上面都是前端開(kāi)發(fā)的標(biāo)配技能,懂得自然都懂,就不說(shuō)太多了,但是該碰到的坑自然都會(huì)遇到.
主要這么幾個(gè):
- 全局污染
好的規(guī)范自然能夠極大方便重用樣式減少代碼,但是別說(shuō)多人協(xié)作開(kāi)發(fā),即使個(gè)人維護(hù)都可能碰到多種樣式覆蓋,權(quán)重優(yōu)先級(jí)混亂,冗余重復(fù)屬性過(guò)多,于是各種內(nèi)聯(lián)樣式,!important強(qiáng)制最先等寫(xiě)法,雖然也有其他方案如功能屬性class拆分避免這種窘境,但是增大開(kāi)發(fā)的參與難度,很難形成一套適用標(biāo)準(zhǔn),起碼我覺(jué)得太繁瑣了.
- 命名煩惱
元素嵌套越深,如果想命名語(yǔ)義化明確點(diǎn)就可能導(dǎo)致越來(lái)越長(zhǎng)越復(fù)雜的命中規(guī)則,而有一些一次性的樣式也不得不遵循這種規(guī)則,否則用內(nèi)聯(lián)樣式替代
- 樣式壓縮
因?yàn)闃邮綄?duì)應(yīng)到具體的引用屬性id,class,選擇器等,這一塊是沒(méi)辦法省略的,嵌套越深入選擇器前綴可能就越長(zhǎng),例如#A .B .C .D p{}這種
預(yù)處理器只是簡(jiǎn)化開(kāi)發(fā)寫(xiě)法,實(shí)際編譯完成也就這個(gè)樣,本質(zhì)上的問(wèn)題沒(méi)有得到解決.
CSS-in-JS
React本身沒(méi)有定義樣式的主張,而是用第三方庫(kù)提供的CSS-in-JS.這里是一些實(shí)現(xiàn)的對(duì)比,之所以會(huì)出現(xiàn)種類繁多的第三方庫(kù)是因?yàn)樗鼈儗?shí)現(xiàn)功能的支持有所區(qū)別,主要在
- Automatic Vendor Prefixing (自動(dòng)添加前綴)
- Pseudo Classes (偽類)
- Media Queries (媒體查詢)
- Styles As Object Literals (對(duì)象字面量樣式)
- Extract CSS File (提取CSS文件)
例如React的官方示例原生style
屬性使用
style
?屬性接受具有駝峰命名屬性的 JavaScript 對(duì)象,而不是 CSS 字符串。愛(ài)掏網(wǎng) - it200.com 這與 JavaScript DOM 的?style
?屬性一致,但是更高效,并且防止XSS安全漏洞。愛(ài)掏網(wǎng) - it200.com 例如:
const divStyle = { color: 'blue', backgroundImage: 'url(' + imgUrl + ')', }; function HelloWorldComponent() { return Hello World!; }
注意:
- 樣式不自動(dòng)進(jìn)行兼容。愛(ài)掏網(wǎng) - it200.com 要支持舊版本的瀏覽器,您需要提供相應(yīng)的樣式屬性
- React 會(huì)自動(dòng)為某些內(nèi)聯(lián)樣式的數(shù)字屬性值附加一個(gè) “px” 后綴。愛(ài)掏網(wǎng) - it200.com 如果你想使用 “px” 以外的單位,請(qǐng)明確指定單位,并將該值指定為字符串
- 并不支持所有的 css,例如媒體查詢,
:before
和:nth-child
等 pseudo selectors
然后我們也能用一些其他的CSS-in-JS庫(kù)解決,我就拿比較多人使用支持功能比較完善的來(lái)舉例一下,下面方案都屬于這種,但是傾向和用法上有一定區(qū)別:
aphrodite
Framework-agnostic CSS-in-JS with support for server-side rendering, browser prefixing, and minimum CSS generation.
Support for colocating your styles with your JavaScript component.
支持功能
- 不強(qiáng)制和React搭配才能使用
- 支持媒體查詢無(wú)需window.matchMedia
- 支持偽選擇器像
:hover
,:active
等等,不需要在組件中存儲(chǔ)懸停或活動(dòng)狀態(tài)。愛(ài)掏網(wǎng) - it200.com:visited
也能良好支持 - 支持自動(dòng)全局@font-face檢測(cè)和插入
- 在指定多個(gè)樣式時(shí),尊重優(yōu)先順序
- 不需要AST轉(zhuǎn)換
- 只向DOM中注入渲染所需的確切樣式。愛(ài)掏網(wǎng) - it200.com
- 可以用于服務(wù)器渲染
- 低依賴,小(20k,壓縮后6k)
- 沒(méi)有外部的Css文件生成
- 自動(dòng)添加前綴
示例
import React, { Component } from 'react'; import { StyleSheet, css } from 'aphrodite'; class App extends Component { render() { return This is red. This turns red on hover. This turns red when the browser is less than 600px width. This is blue. This is blue and turns red when the browser is less than 600px width. ; } } const styles = StyleSheet.create({ red: { backgroundColor: 'red' }, blue: { backgroundColor: 'blue' }, hover: { ':hover': { backgroundColor: 'red' } }, small: { '@media (max-width: 600px)': { backgroundColor: 'red', } } });
當(dāng)然也很多人不太接受這種方式書(shū)寫(xiě)Css,還把html結(jié)構(gòu)嵌套一堆className={css()}
的寫(xiě)法.
styled-components
使用標(biāo)記的模板文本和CSS的強(qiáng)大功能,樣式組件允許您編寫(xiě)實(shí)際的CSS代碼來(lái)樣式化組件。愛(ài)掏網(wǎng) - it200.com它還刪除了組件和樣式之間的映射——將組件用作低級(jí)樣式結(jié)構(gòu)再簡(jiǎn)單不過(guò)了!
風(fēng)格組件既兼容React(用于web),也兼容React Native——這意味著它甚至是真正通用的應(yīng)用程序的完美選擇!
示例
import React from 'react'; import styled from 'styled-components'; // Create areact component that renders an which is // centered, palevioletred and sized at 1.5em const Title = styled.h1` font-size: 1.5em; text-align: center; color: palevioletred; `; // Create a
react component that renders a with // some padding and a papayawhip background const Wrapper = styled.section` padding: 4em; background: papayawhip; `; // Use them like any other React component – except they're styled! Hello World, this is my first styled component!
優(yōu)點(diǎn)
- 直接將樣式組件化,移除樣式和組件的映射關(guān)系
- 支持組件繼承,方便復(fù)用
- 和原有CSS方式無(wú)障礙搭配使用
styled-jsx
這是我查資料的時(shí)候了解到的一種方案,因?yàn)闆](méi)有實(shí)際用過(guò),所以我只貼上它的功能示例
主要功能
- 完全的CSS支持, no tradeoffs in power
- 運(yùn)行時(shí)大小僅為3kb(從12kb壓縮為gzip)
- 完全隔離:選擇器、動(dòng)畫(huà)、關(guān)鍵幀
- 內(nèi)置CSS瀏覽器前綴
- 非常快速、最小和高效
- 非服務(wù)器渲染時(shí)高效運(yùn)行注入
- 面向未來(lái):相當(dāng)于服務(wù)器可渲染的"Shadow CSS"
- 支持源映射
- 支持動(dòng)態(tài)樣式和主題
- 通過(guò)插件進(jìn)行CSS預(yù)處理
示例
export default () => (only this paragraph will get the style :)
{ /* you can includes here that include other s that don't get unexpected styles! */ }
)
CSS Module
這是我在學(xué)習(xí)webpack的Css-loader的時(shí)候了解到的一種方案,現(xiàn)在在使用的方案
CSS Module是一個(gè)CSS文件,默認(rèn)所有類和動(dòng)畫(huà)命名都限于局部范圍.所有資源(url(...))
和@imports
都在模塊請(qǐng)求格式.
Css模塊會(huì)被編譯成底層交換格式像ICSS
或者Interoperable CSS
,但是書(shū)寫(xiě)格式和普通CSS文件一樣.
當(dāng)從JS模塊導(dǎo)入CSS模塊時(shí),它導(dǎo)出一個(gè)具有從本地名稱到全局名稱的所有映射的對(duì)象。愛(ài)掏網(wǎng) - it200.com
CSS
/* style.css */ .className { color: green; }
JSX
import { PureComponent } from 'react'; import styles from './index.scss'; class Page2 extends PureComponent { constructor(props) { super(props) } render() { return ( ); } }
當(dāng)然這不是只限于React,使用webpack或者其他打包工具的方式都能支持使用.
優(yōu)點(diǎn)
模塊化和可重用性
- 沒(méi)有沖突
- 顯性依賴
- 不會(huì)污染全局
- 可以配合預(yù)處理器使用
- API少,開(kāi)發(fā)單獨(dú)CSS文件寫(xiě)法基本一致