請用CSS命名“一條粉色的蕾絲女式內褲”

命名是我認為 CSS 裡最難的問題沒有之一,特別是別人的命名。
管理 CSS 就好比管理“內褲”
我們都知道,CSS 是一個不強調 邏輯 ,而更看中表現的一種 所見即所得 的語言。你寫了一個屬性它就有了這個樣式,你之前寫了,你現在又寫一個,它就以你最新寫的這個為準(在不考慮選擇器優先順序的情況下)。這種愉悅感是別的開發語言所不具備的。就好比你嗑瓜子一下,你嗑一下都會能給你一個反饋,你就能一直嗑下去。而這也是 CSS 讓我著迷的原因之一。
CSS 的作用域是全域性的,這樣我們能很輕易的覆蓋一個 CSS 樣式,即使之前的人程式碼寫的不是那麼的優雅。可是也正因為這樣,當我們不想覆蓋別人的樣式,或者自己之前寫的樣式的時候,這就變成了一個世界難題。因為此時我們面臨的問題不再是寫樣式這麼簡單,而是升級成了 程式碼管理 的問題。
CSS 不像其它有邏輯性的語言,有比較多的程式碼管理方式。你能管理 CSS 的工具只有兩個,一個是 檔案引用 ,另一個則是 命名 。所以你能看到的所有講 CSS 命名規則的方法不管是BEM 還是SMACSS ,其實都是在講 CSS 程式碼管理的問題。

對於CSS的管理,我這邊舉個不恰當但是很貼切的方式,就是類似於日常生活中內褲的管理,是的就是你日常穿的內褲,和 CSS 中的“類庫”諧音(我太有才了)。
假設你爸是挖礦的,你家很有錢。而你又特別喜歡買內褲,赤,橙,黃,綠,青,藍,紫,彩色的,蕾絲的,莫代爾的,純棉的,緊身的... 各式各樣的內褲共計9999條(加上你現在身上穿的那一條,剛好10000條)。請問你要怎麼管理這10000條內褲?
你家有錢,很簡單,你買 100 間房間,按照自己“喜歡”的分類,每個房間各放100條內褲。然後每間房間裡面又按照自己“熟悉”的規則,把內褲進行排列。有錢就是任性有沒有?
而這一個個的房間就好比我們 CSS 中的一個個檔案,房間裡內褲的編號,就好比我們的 class
類名。這邊可以看到,我有把“喜歡”,和“熟悉”加上引號。因為對於自己喜歡和熟悉的東西,對於其它的人來說都基本上是不熟悉的。不信你可以問問你的同事,你們歸類內褲的規則很大概率和你是不一樣的(最好問同性的同事吧,不然小心被告職場性騷擾)。
你媽比你更會管理你的“內褲”
所以要怎麼辦呢?此時老媽就派上用場了。你媽媽的生活經歷肯定比你豐富,並且她的生活經歷也有可能和樓下廣場舞大媽們聊過的,所以說稱得上是一項通用技能。於是遇到找內褲的問題,我們大家的第一反應通常是問媽媽。

在 CSS 世界裡也是一樣的。有很多管理 CSS “內褲”的媽媽,而這邊我舉一個相對比較有名的阿姨 BEM :
<styles> .brief{ /* 描述:貼身的下身內衣; */ } .brief--type{ /* 大小:中號; */} .brief--male{ /* 適合性別:男; */ } .brief--male__type{ /* 顏色:黑色; */} </styles> <div class="brief brief--male"> <div class="brief__type brief--male__type">一條黑色的男式中號內褲</div> </div> 複製程式碼
可以看到這位阿姨管理“內褲”還是很有一套的,首先它的可讀性是非常好的,也能解決不同人員之間,命名不規範的問題。然後你上午逛街看上了一條紅色女士內褲,準備買來送給女朋友。
<styles> .brief{ /* 描述:貼身的下身內衣; */} .brief--type{ /* 大小:中號; */} .brief--male{ /* 適合性別:男; */ } .brief--male__type{ /* 顏色:黑色; */} .brief--female{ /* 適合性別:女; */} .brief--female__type{ /* 顏色:紅色; */ } </styles> <div class="brief brief--male"> <div class="brief__type brief--male__type">一條黑色的男式中號內褲</div> </div> <div class="brief brief--female"> <div class="brief__type brief--female__type">一條黑色的男式中號內褲</div> </div> 複製程式碼
BEM 阿姨到這裡表現都是非常不錯的,在保證程式碼可讀性的情況下,拓展性也是很好的。
晚上吃完宵夜的時候,怕自己上午買的內褲女友不喜歡,又多買了“一條粉色的蕾絲女士內褲”。
<styles> .brief{ /* 描述:貼身的下身內衣; */ } .brief--type{ /* 大小:中號; */} .brief--male{ /* 適合性別:男; */ } .brief--male__type{ /* 顏色:黑色; */} .brief--female{ /* 適合性別:女; */} .brief--female__type{ /* 顏色:紅色; */ } .brief--female2{ /* 型別:蕾絲; */} .brief--female2__type{ /* 顏色:粉色; */ } </styles> <div class="brief brief--male"> <div class="brief__type brief--male__type">一條黑色的男式內褲</div> </div> <div class="brief brief--female"> <div class="brief__type brief--female__type">一條紅色的女式內褲</div> </div> <div class="brief brief--female brief--female2"> <div class="brief__type brief--female2__type">一條粉色的蕾絲女式內褲</div> </div> 複製程式碼
可能你媽媽不知道蕾絲是啥,就不知道怎麼管理你的內褲了?但是媽媽項來是不願意承認自己的錯誤的,於是她肯定會開罵了:你上午不是剛買了內褲嗎,怎麼又買?我才懶得管你。你自己買的內褲你自己弄吧!
而此時你就悲劇了,“一條粉色的蕾絲女式內褲”,請問用你媽媽的 BEM 方式要怎麼命名?像這樣 .brief--female__type--lace
? 我想此時你是崩潰的。
到這裡不知道大家有沒有發現這件事情不對的地方?當引入 BEM 之後,我們已經完全不能享受到買內褲和使用內褲的樂趣了。
我們更多在做的事情是什麼?是 命名 ,還有 維護 這套命名規則。如果換到工作場合,媽媽這個角色可就是你的同事了。如果你同事看到你用了一個 .brief--female__type--lace
這樣的類名來管理你的“內褲”,你只能感謝他的不殺之恩了。
我們每次找不到自己內褲的時候,會本能問:“媽!我昨天穿的那條內褲在哪兒啊?”
媽媽通常會不耐煩的回答:“昨天不就告訴你了在第一個櫃子的第二個抽屜的第一格,這樣的問題你到底還要問幾遍?”
這是不是很像工作中,你問你同事:“誒,你昨天給我說的,你之前封裝的那個讓按鈕爆炸的那個 class
叫啥啊?”
發現問題沒有?我們要的是內褲,而內褲放在哪裡這件事,並不是我們關心的重點。
“媽,你能把我昨天穿的那條內褲給我一下嗎?”
啪,你媽直接就把內褲扔給你了。
這是不是你更希望得到的結果。
把你的內褲都換成一次性內褲
只是因為我們都太習慣建立 class
類名了,導致我們在寫樣式的時候,第一步竟然不是樣式本身而是建立一個 class
。
就好比你一條內褲都還沒有買,你媽媽都已經提前給你訂好了,按照各種款式命名的裝內褲的盒子。能做到連你自己都不知道要買啥樣的內褲,卻能幫你無中生有的歸好類的人也只有你媽媽了。
你有沒有想過,你都是能買得起上萬條內褲的人了,為啥不自己建了一個內褲工廠,你想要什麼樣的內褲,你直接打個電話給你的助手,他就直接送到你的面前,穿完了你就扔掉。
每天都穿新內褲還不帶重樣的。管理內褲什麼的,與你無關,也解放了你媽媽時間。家庭一下子就和睦了,有沒有?
而這種方式換到 CSS 裡面就是類似於這樣:
<div style="/* 描述:貼身的下身內衣;大小:中號;適合性別:男; 顏色:黑色;*/ ">一條黑色的男士內褲</div> <div style="/* 描述:貼身的下身內衣;大小:中號;適合性別:女; 顏色:紅色;*/ ">一條紅色的女式內褲</div> <div style="/* 描述:貼身的下身內衣;大小:中號;適合性別:女; 型別:蕾絲; 顏色:粉色;*/ ">一條粉色的蕾絲女式內褲</div> 複製程式碼
是的,不要懷疑你的眼睛,我們通過 style
直接寫屬性,就能最直接的告訴別人 “一條粉色的蕾絲女式內褲” 的樣子。是不是任何人都能看懂?而這也是我認為最符合 CSS “所見即所得” 的方式。
這裡還有一個更值得思考的問題,我們在這裡甚至都弱化了內褲本身這個名字。我都把一個你想要的黑色的可以遮擋私處的貼身內衣給你穿上了,你覺得你還在乎它叫啥嗎?

而此時本文的重點來了,CSS 是什麼?CSS 是 層疊樣式表 ,而 class
(類名)顯然不是,它只是 CSS 和 HTML 之間的 鉤子 。而真正的樣式其實是這些:
描述:貼身的下身內衣; 大小:中號; 適合性別:男; 顏色:黑色; /* ... */ 複製程式碼
我們之所以會需要去 管理程式碼 ,很大一部分原因是因為我們想要去 複用 它造成的。這個理論不僅限於 CSS,對於大多數的語言都是適用的。
簡單的來說,現買現用,穿完就扔的內褲,是不需要你花時間和精力去管理的。你之所以需要用箱子去裝你的內褲,甚至還需要給不同的箱子編上不同的名字,就是希望下次想穿的時候能夠快速的找到它。
如果你不想管理你的內褲,最簡單直接的方式就是,把它們都換成一次性內褲。
說得高階一點就是完全放棄空間複雜度(浪費儲存資源),以換取時間複雜度(管理時間)的自由。
管理內褲的原材料而不是內褲
所以 程式碼複用 和 程式碼管理 其實是不是我們以為的 從屬 關係,而是兩個 對立 面的關係。那我們要怎麼平衡這兩個點呢?
在程式碼的世界裡,只要對方的“內褲”是我“襠下”需要的,我們甚至巴不得複用(不好意思,忍不住開車了)。因為對於CSS來說複用樣式,其實是成本很低的一件事情,我們只需要知道一個樣式的 class
,就能通過這個 class
複用我們想要的樣式。真正的噩夢是 class
的命名和維護 class
。你想象要複用10000條內褲,我們在管理這10000條內褲的同時,還得管理用來管理這10000條內褲的 命名規則 。這是一件多麼痛苦的事情?
這聽起來真的是繞口,然而 CSS 的現狀就是這樣。那有沒有一種方式是可以跳出這個怪圈的呢?答案當然是有的,就是放棄複用“內褲”這個想法,而是要思考怎麼複用製作內褲的 原材料 。
當我們的視角進入到複用內褲原材料這個更微觀的世界的時候,你就會發現之前的問題都迎刃而解了。很簡單,來我們嘗試著把10000條內褲,拆解為可複用的原材料。
- 布型別:棉,麻,滌綸,氨綸,莫代爾...
- 顏色:赤,橙,黃,綠,青,藍,紫...
- ...
基於之前的例子,我們現在的程式碼會變成什麼樣的呢?
<style> .貼身的下身內衣{ } .中號{ } .男{ } .女{ } .黑色{ } .紅色{ } .粉色{ } .蕾絲{ } </style> <div class="/* 貼身的下身內衣 中號 男 黑色 */ ">一條黑色的男士內褲</div> <div class="/* 貼身的下身內衣 中號 女 紅色 */ ">一條紅色的女式內褲</div> <div class="/* 貼身的下身內衣 中號 女 粉色 蕾絲 */ ">一條粉色的蕾絲女式內褲</div> <div class="/* 紅色 */">一匹紅色的馬</div> 複製程式碼
可以看到我們需要維護的東西,一下從 10000 條內褲降到了幾十種原材料。這些原材料是不需要你去思考它們名字的。更驚奇的是,這些原材料可不只用於內褲上,它還可以應用到內衣,衣服,褲子,鞋子...等等一系列的東西上。
你甚至可以用這個原材料,把一匹馬塗成紅色的。發現沒有,這就是我們視角改變了之後,整個 思維方式 的巨大改變。
之前有講過,在 CSS 世界裡,複用是成本很低的事情,也就是說,我們複用1個原材料和複用10個原材料是沒有本質區別的。
內褲是工業品不是藝術品
到這裡可能有的同學會說,你這個原材料拆分的明顯沒對,布型別不是還有竹炭纖維,甚至太空材料的,顏色還有紅藍漸變或者五彩斑斕的黑。
對於我們大多數男性程式員來說,內褲無非就是棉的和不是棉的兩種,顏色無非就是黑,白,灰。即使不是程式設計師,你也很難會發現,普通的人會買到,赤,橙,黃,綠,青,藍,紫這麼多種顏色的內褲。
舉這個例子是想說明什麼,內褲是 工業品 而不是 藝術品 。工業品註定會控制原材料的種類以降低成本的。而真正會把內褲當藝術品的人,也就不會因為沒錢,而不會去考慮複用內褲的問題。
在我們網頁的開發也是一樣的,如果你的網站不是走藝術類的網站,你卻發現你的原材料提供商(設計師),光是從顏色上就給你提供了超過了十幾二十幾種顏色,那他一定是有問題的。
如果你的設計師,是對自己的設計語言是有極致約束能力的,那對於我們開發者來說這真的是一件非常開心的事情。
內褲原材料管理方法論Atomic CSS
這種將樣式原子化的思維方式就叫做 Atomic CSS (簡稱 ACSS )。 我花了這麼大的篇幅,還花了這麼多的心思去借用“內褲”舉例子,就是希望大家能先明白這是一種 思維方式 。而不只是一個 工具 這麼簡單。
我在團隊裡至少分享了四五次關於 ACSS 主題,也依然存在著非常大的爭議,就好比你想讓一個一直基於 DOM 開發的前端程式設計師,在一瞬間就完全接受 React 的元件化思維一樣是很困難的。
要接受 ACSS 都已經是很難的事情,更何況要深入去思考它的優劣。在國內我幾乎只看到我的男神 “張鑫旭”有略微深入的介紹過這套理論(當然有可能是我只關注了他一個人的原因)。
而我是 12 年還沒有畢業的時候就已經在研究 OOCSS(和 ACSS 角度不同,但是思維方式卻是高度一致的)了。毫不吹噓的說,基於這套理論,我是我遇到的前端程式設計師中 CSS 原型稿寫的最快的程式設計師(可能我認識的人本來就不多)。有興趣的同學可以去我的 ofollow,noindex">github 看一下 。因為最近一直在用 SASS,所以很多新的思考和沉澱,已經很久沒有更新了,這裡只是為自己打個廣告,重點是實現方式,程式碼和文件後續我會再跟進一下。
為啥這麼多年我沒有推 ACSS 呢?沒有名氣:joy:,你說的話就很少有人會靜下心來聽,更別提會去思考了。因為最近發的一篇文章在掘金上得到滿多同學支援的,所以覺得可以蹭蹭熱度,略微試著努力推一下 ACSS。
當然更主要的原因是,目前元件化思維正是當下最流行的時候。而 ACSS 是和元件化思維特別 Match 的一種方式。所以特別希望 ACSS 能被大家看到。我會盡自己最大的努力從不同的角度,寫幾篇文章,來幫助大家瞭解 ACSS。當然個人能力有限,如果不恰當的地方可以給我留言,我們一起探討。用不用 ACSS 大家可以根據自己實際專案來定,但是這種思維方式,錯過了真的是種遺憾。