注:原文作者是來自facebook的前端基礎(chǔ)設(shè)施團(tuán)隊的Christopher Chedeau。
大規(guī)模項目中面臨的css問題:
- 全局命名空間
- 依賴
- 無用代碼移除
- 壓縮
- 共享常量
- 定制化
- 隔離
舉個Button的例子:
/* button.css */
.button{
background: #f6f7f8 url(/images/button/background.png) repeat-x;
border: 1px solid #cdced0;
border-radius: 2px;
box-shadow: 0 1px 1px rgba(0,0,0,0.05);
}
.button-depressed{
background-color: #4e69a2;
border-color:#c6c7ca;
color:#5890ff;
}
以上我們設(shè)計了一個button,存在常態(tài)和按下狀態(tài)。
全局變量
在w3schools.com的JavaScript的最佳實踐中,建議避免使用全局變量。

對于我來說,在css中仍然存在全局變量是一件讓人瘋狂的事情。在js編程中,我們很早就知道全局變量是不好的實踐。
我們學(xué)習(xí)使用局部變量、自執(zhí)行函數(shù)、模塊化編程來解決全局變量的問題。
但是,在bootstrap的css中,存在超過600個的全局變量。
在Facebook,我們使用一種css擴(kuò)展來解決這個問題。
/* button.css */
.button/container{
/* dropdown.css */
.dropdown/container .button/container{
這種方式,只有在button.css文件中的button/container樣式才會參與build,如果視圖在dropdown.css中使用,它將不會參與build.
如果需要導(dǎo)出全局變量,可以采用以下寫法:
.button/container/public{
.dropdown/container .button/container/public{
調(diào)用部分:
/* button.css */
.button/container{
/* button.js */
<div className={cx('button/container')}>
因為button/container不是有效的classname,因此我們的調(diào)用方式需要發(fā)生變化,調(diào)用cx(class extension)來完成轉(zhuǎn)換。
依賴
/* button.css */
.button/container{
/* button.js */
requireCSS('button')
<div className={cx('button/container')}>
以前我們把css打包到一個獨立的文件中,現(xiàn)在我們把它們分割成一個個獨立的文件,分別引入依賴。
很久以來,我們一直要求開發(fā)者只引入需要的css文件。但是如果其他人引入了某個css文件,它依舊會存在。
現(xiàn)在我們有了cx,它會進(jìn)行靜態(tài)分析,可以自動注入。
無用代碼移除
因為cx是唯一生成樣式的方式,這樣我們可以解決最麻煩的問題:移除無用的代碼。
壓縮
通過cx可以最小化所有的classname,讓js和css文件更小。
共享常量
.button/container{
/* keep in sync with button.js */
padding:5px;
//Keep in sync with button.css
var buttonPadding=5;
很長一段時間,我們采用注釋或者命名約定的方式來共享常量。
現(xiàn)在我們引入了css變量。
/* button.css */
.button/container{
padding:var(button-padding);
var buttonPadding = cssVar('button-padding');
$CSSVar = array(
'button-padding' => 5,
);
由于facebook很多項目使用了php語言,所以我們在php中定義了css變量。
此時,我們依舊存在兩個沒有解決的問題:定制化和隔離。
css in js方案
這一刻我們等了很久...
/* button.js */
var styles = {
container: {
backgroud: '#f6f7f8 url(/images/button/background.png) repeat-x',
border: '1px solid #cdced0',
borderRadius: 2,
boxShadow: '0 1px 1px rgba(0,0,0,0.05)'
},
depressed: {
backgroundColor: '#4e69a2',
borderColor: '#c6c7ca',
color: '#5890ff'
}
};
我們使用內(nèi)聯(lián)樣式來渲染
<div style={styles.container}>
內(nèi)聯(lián)樣式并沒有那么糟糕。
首先:我們依舊在一個獨立的文件中編寫樣式;
其次:style實際比class語義上更好;
最后:我們并沒有直接應(yīng)用style,而是通過React Virtual DOM。
前五個問題順利解決。
定制化
/* button.js */
propTypes:{
isDepressed:React.PropTypes.bool,
style:React.PropTypes.object,
},
<div style={m(
styles.container,
this.props.isDepressed && styles.depressed,
this.props.style
)}>
于是,我們同時解決了后兩個問題。很明顯,當(dāng)在js中寫樣式,樣式中的class只會獨立出現(xiàn)相互隔離。
結(jié)論
我并不是要說服你們拋棄css,使用js。
我們有了大量的css庫,例如less、sass...但是他們都沒有解決上面的7大問題。
css也并不是web中存在底層缺陷的唯一部分,但是React在嘗試解決他們中的一些問題。
我希望你們打破天花板,面對搭建web服務(wù)面臨的困境,去思考、討論并解決。