![如何管理 CSS “內褲”](https://i.iter01.com/images/a832fabd2f13b7f24940d146f7214c4fe07c19a8d386ae745e2268d7adc5451d.png)
修正於 2018-10-21。為了文章生動,之前用了太多過於誇張的修飾手法,以至於讓很多朋友忽略了內容本身。基於網友的評論和指出的不足。略微修改了文風,刪除了多餘的廢話,梳理了文章大綱。
命名 是我認為 CSS 裡最難的問題沒有之一。
CSS 是一個不強調邏輯,而更側重表現的一門所見即所得的語言。你寫了一個屬性它就有一個樣式,就好比嗑瓜子,你每嗑一下都能及時的得到一個獎勵。這種愉悅感是別的開發語言所不具備的。
CSS 也不像其它側重邏輯的語言,有比較多的程式碼管理方式。你能管理 CSS 的工具只有兩個,一個是檔案引用,另一個是命名。通常為了減少頁面 HTTP 的請求,我們會盡可能的將 CSS 檔案合併。於是靠檔案引用這個方式來管理 CSS 的這條路也就顯得特別的窄了。
我們都知道 CSS 的作用域是全域性的,只要你引用了一個 CSS 檔案,它就會影響你整個頁面。於是,CSS 程式碼管理的重任就全壓在了命名這一條路上。
所以簡單的說,你能搞定 CSS 的命名,就能管理好 CSS。
管理 CSS 就好比管理“內褲”
![如何管理 CSS “內褲”](https://i.iter01.com/images/2c4e4a5c46765d927dacccee241b25060a8b1d4105a398f45dd943ae236ce264.jpg)
對於 CSS 的管理,我這邊舉個不恰當但是很貼切的類比,就是類似於日常生活中內褲的管理,是的就是日常穿的內褲,和 CSS 中的“類庫”諧音(我太有才了)。
前面有講到,對於 CSS 的管理我們基本只能通過命名的方式去管理。這聽起來似乎是一件值得開心的事,因為只有一條路,所以大家都沒得選。然而出乎我們意料的是,即使只有一條路,大家也是走得五花八門。
舉個例子,比如我們有 7 條不一樣的內褲,如果只用命名的方式去管理內褲,會出現多少種可能?
按日期 | 按顏色 | 按材質 | 按花紋 | ... |
---|---|---|---|---|
.星期一{} |
.紅色{} |
.純棉{} |
.格子{} |
... |
.星期二{} |
.黃色{} |
.滌綸{} |
.橫條紋{} |
... |
.星期三{} |
.藍色{} |
.氨綸{} |
.波點{} |
... |
... |
... |
... |
... |
... |
就像一千個讀者就有一千個哈姆雷特一樣,不同的人對於同一件事物的命名方式是不一樣的。因為對於自己喜歡和熟悉的東西,對於其它的人來說都基本上是不熟悉的。不信你可以問問你的同事,你們歸納和命名內褲的方式很大概率是不一樣的。所以這個的可能性是無限的。
當然如果只有 7 條內褲,你和我的命名方式不一樣就不一樣唄,我只要能看懂基本也就還好。可是,當我們對於內褲的管理上升到了庫的概念的時候,一切就沒有那麼容易了。
假設你爸是挖礦的,你家很有錢。而你又特別喜歡買內褲,赤,橙,黃,綠,青,藍,紫,彩色的,蕾絲的,莫代爾的,純棉的,緊身的... 各式各樣的內褲共計 100 ,請問你要怎麼命名這 100 條內褲?
此時你會發現上面管理 7 條內褲的方式,任意一個方式都顯得力不從心。所以要怎麼辦呢?
管理 CSS “內褲” 的通用方法
之前有講到,管理 CSS 的問題就是 CSS 命名的問題。所以我們看看目前現有的最流行的解決 CSS 命名的通用解決方案 BEM。
![如何管理 CSS “內褲”](https://i.iter01.com/images/84f8c90600d765909f2b1cf5128a4b421eec151ce644adc0a016142da4602eeb.png)
因為我不是 BEM 的擁護者,之前舉的例子被網友評論打臉了,這邊就直接講結果吧。
.block__element--modifier{ /* */ }
複製程式碼
很直觀的可以看到引用了 BEM 之後,我們的 CSS 就有了,三級的作用域。這個怎麼解釋呢?
很簡單,之前我們命名 7 條內褲的方式是一維的。但是用 BEM 之後,可以看作是一個長寬高各 10 的三維立方體。你要找一個東西,你只需要知道對應的長寬高對應的座標就能找到。類似:
.長1__寬2--高3{ /* */}
複製程式碼
是不是一下子就簡單了很多。BEM 系統的解決了 CSS 的命名問題,並且它的維護性和擴充性也是非常棒。所以它是非常值得推薦的管理 CSS 程式碼的解決方案。感興趣的同學可以下來自己瞭解一下。
這裡呢,我是想說是我不喜歡 BEM 的點(感覺又要打臉了)。與其說不喜歡 BEM,倒不如說我連 CSS 命名本身都不喜歡。為什麼這麼說呢?因為對我來說命名真是一件非常痛苦的事情。
在我寫程式碼的時候經常會遇到這樣的問題,有兩個非常像的模組,但是它們又有些許的不同,為了公用他們相同的樣式,你又必須將這部分抽象出來,可是抽象出來的這個部分,又不能傾向於這兩者其中一個,你要怎麼命名呢?就好比:
/* 這個例子不是 BEM 的正確使用姿勢,這裡只是作為參考 */
.櫃1__屜2--內褲,.櫃2__屜2--內褲{
名稱:貼身的下身內衣;
大小:中號;
顏色:粉色;
}
.櫃1__屜2--內褲{
適合性別:男;
}
.櫃2__屜2--內褲{
適合性別:女;
款式:蕾絲;
}
<div style="櫃1__屜2--內褲">一條內褲</div>
<div style="櫃2__屜2--內褲">另一條內褲</div>
複製程式碼
你想為上面這兩條內褲公共的部分抽象一個通用的類,請問要怎麼命名?然後更可怕的是,此時又來了第三條內褲:
.櫃2__屜3--內褲{
名稱:貼身的下身內衣;
大小:中號;
顏色:紅色;
適合性別:女;
款式:蕾絲;
}
<div style="櫃2__屜3--內褲">又一條內褲</div>
複製程式碼
然後你又發現,之前好不容易命名好的通用類名,不能用到這第三條內褲上。然而第二條內褲和第三條內褲又有了公用的部分,這部分是不是又可以進一步抽像呢?一旦抽象,就意味著又要取一個名字,然而此時你又該怎麼取名呢?這次擴充兩步,我的已經崩潰了。
當然在實際開發中,我相信大家有更優秀的命名方式,來解決這個實際的問題。這裡只是用這種誇張的方式來證明命名是一件非常不容易的事情(不用較真我的使用姿勢是否正確)。
你要的是內褲,不是內褲放在哪裡
我們每次找不到自己內褲的時候,會本能問:“媽!我昨天穿的那條內褲在哪兒啊?”
媽媽通常會不耐煩的回答:“昨天不就告訴你了在第一個櫃子的第二個抽屜,這樣的問題你到底還要問幾遍?”
.櫃1__屜2--內褲{
名稱:貼身的下身內衣;
大小:中號;
適合性別:男;
顏色:黑色;
}
複製程式碼
“第一個櫃子第二抽屜”,這聽起來很像 BEM 命名的 的方式,當然它能非常簡單直白的告訴你內褲放在哪裡。
可是不知道大家有沒有想過這樣的問題,如果我們問:“媽!我昨天穿的那條內褲在哪兒啊?” 啪!你媽媽直接就把內褲扔你臉上了,這種方式是不是才是我們更希望看到的結果。是的,要啥內褲座標啊,直接把內褲給我不就好了。我要的是內褲,不是內褲放在哪裡。
CSS 是什麼?CSS 是層疊樣式表,而 class
(類名)顯然不是,它只是 CSS 和 HTML 之間的鉤子。
名稱:貼身的下身內衣;
大小:中號;
適合性別:男;
顏色:黑色;
複製程式碼
這些東西,才是真正意義上的我們想要的“內褲”的樣式。而.櫃1__屜2--內褲
只是一個告訴你 “內褲” 放在哪兒的座標。
那在實際開發過程中,怎麼樣才算是想要內褲的時候,內褲就出現在我們手中呢?
<div style="名稱:貼身的下身內衣;大小:中號;顏色:粉色;適合性別:男;">一條內褲</div>
<div style="名稱:貼身的下身內衣;大小:中號;顏色:粉色;適合性別:女;款式:蕾絲;">另一條內褲</div>
<div style="名稱:貼身的下身內衣;大小:中號;顏色:紅色;適合性別:女;款式:蕾絲;">又一條內褲</div>
複製程式碼
是的,通過 style
直接寫 CSS 屬性,就能簡單粗暴的把“內褲放到別人手中”。而這也是我認為最符合 CSS “所見即所得” 的方式。
想要什麼樣式我就寫什麼樣式,不用花時間去為我的樣式建立一個自認為很好看,但是別人看不懂的類名。我也不用考慮命名汙染的問題,因為根本連命名都沒有。也正因為連命名都沒有,所以也不需要糾結上面提到的任何關於命名讓人頭疼的問題。
只是因為我們大家都太習慣建立 class
了,導致我們在寫樣式的時候,第一步想不是樣式本身而是建立一個 class
。在我看來這是有一點本末倒置的。
總結一下就是:當我想要“內褲”的時候,我希望的是“內褲”就直接出現在我的手裡,而不是得到一個能精確告訴我“內褲”放在哪裡的座標。不管這個座標的命名規則聽起來是有多麼的好。
一旦有了命名,我在管理 100 條“內褲”的同時,還得管理比“內褲”本身量級更復雜的這 100 個類名。
管理內褲的原材料而不是內褲
我們之所以會需要去管理程式碼,很大一部分原因是因為我們想要去複用它造成的。簡單的來說,現買現用,穿完就扔的內褲,是不需要你花時間和精力去管理的。
上一節中我們放棄了複用樣式這個想法,利用 inline css,在解決程式碼管理問題的同時,還得到了一種將重心聚焦在 CSS 樣式本身的程式設計體驗。
正是因為我們放棄了命名,所以才解決了程式碼管理問題,可是想要複用就必定意味著要命名。這聽起來似乎是一個悖論。
那有沒有一種方式是可以跳出這個怪圈的呢?答案當然是有的,那就是放棄管理“內褲”,而是轉向去管理“內褲”的原材料。我們將之前需要管理的 100 條內褲的原材料列舉如下:
- 布型別:棉,麻,滌綸,氨綸,莫代爾...
- 顏色:赤,橙,黃,綠,青,藍,紫...
- ...
基於之前的例子,我們現在的程式碼會變成什麼樣的呢?
<style>
.貼身的下身內衣{ }
.中號{ }
.男{ }
.女{ }
.黑色{ }
.紅色{ }
.粉色{ }
.蕾絲{ }
</style>
<div class="貼身的下身內衣 中號 粉 男">一條內褲</div>
<div class="貼身的下身內衣 中號 粉色 女 蕾絲">另一條內褲</div>
<div class="貼身的下身內衣 中號 紅色 女 蕾絲">又一條內褲</div>
<div class="紅色">一匹紅色的馬</div>
複製程式碼
首先,因為這些原材料都已經是不能拆分的最小單元,所以他們的名字能非常容易的固化下來,形成一個通用的“類庫”。每次建立新專案的時候,你只需要略微的修改就可以複用起來。
雖然為了解決樣式複用的問題我們還是有建立類名,但因為這些命名是不可以拆分並且容易固化的,所以管理的難度會小很多。並且隨著,時間的推移,原材料的膨脹率是非常小的。元件化如果做得好,原材料甚至可以做到只減不增。
更驚奇的是,這些原材料可不只用於內褲上,它還可以應用到衣服,褲子,鞋子...等等一系列的東西上。你甚至可以用這個原材料,把一匹馬塗成紅色。這就是我們視角改變了之後,整個思維方式的巨大改變。而是將複用發揮到極致。
這種將樣式原子化的思維方式,是來自雅虎團隊的 Atomic CSS (簡稱 ACSS )。毫不吹噓的說,基於這套理論,我是我遇到的前端程式設計師中 CSS 原型稿寫的最快的程式設計師(可能我認識的人本來就不多)。
在這裡有必要解釋一下,我全篇所有的論證都是基於“庫”的概念的。如果你只是建立一個簡單的運營活動頁 ACSS 那你只能用到 ACSS 快這一個特性,而它更大的優勢程式碼管理這一塊是體現不出來的。
因為元件化思維正是當下最流行的時候。而 ACSS 是和元件化思維特別 Match 的一種方式。所以特別希望 ACSS 能被大家看到。當然個人能力有限,如果不恰當的地方可以給我留言,我們一起探討。
內褲是工業品不是藝術品
到這裡可能有的同學會說,你這個原材料拆分的明顯沒對,布型別不是還有竹炭纖維,甚至太空材料的,顏色還有紅藍漸變或者五彩斑斕的黑。
對於我們大多數男性程式設計師來說,內褲無非就是棉的和不是棉的兩種,顏色無非就是黑,白,灰。即使不是程式設計師,你也很難會發現,普通的人會買到,赤,橙,黃,綠,青,藍,紫這麼多種顏色的內褲。
舉這個例子是想說明什麼,內褲是工業品而不是藝術品。工業品註定會控制原材料的種類以降低成本的。而真正會把內褲當藝術品的人,也就不會因為沒錢,而不會去考慮複用內褲的問題。
在我們網頁的開發也是一樣的,如果你的網站不是走藝術類的網站,你卻發現你的原材料提供商(設計師),光是從顏色上就給你提供了超過了十幾二十幾種顏色,那他一定是有問題的。
如果你的設計師,是對自己的設計語言是有極致約束能力的,那對於我們開發者來說這真的是一件非常開心的事情。
相關閱讀
- quickLayout.css-快速構建結構相容的web頁面 @張鑫旭
男神作品,強推; - 「英」在元件化浪潮中重新思考CSS @johnpolacek
雖然是英文,但是網頁做得像PPT一樣,通俗易懂,強推; - 「CSS思維」元件化VS原子化 @ziven27
我的一篇專門解釋“元件化思維” 和 “原子化思維” 區別的文章; - ACSS 官網 @雅虎
這個思維最早應該是雅虎推出來的,最近他們有在推 React ACSS - 關於HTML語義和前端架構 @大漠;
- 「譯」CSS通用類和“關注點分離” @adamwathan;
- 「英」Styling React @SURVIVEJS;
- 「英」CSS最佳實踐探討 - Atomic CSS @smashingmagazine;
“”