如何管理 CSS “內褲”

ziven27發表於2019-03-02

如何管理 CSS “內褲”

修正於 2018-10-21。為了文章生動,之前用了太多過於誇張的修飾手法,以至於讓很多朋友忽略了內容本身。基於網友的評論和指出的不足。略微修改了文風,刪除了多餘的廢話,梳理了文章大綱。

命名 是我認為 CSS 裡最難的問題沒有之一。

CSS 是一個不強調邏輯,而更側重表現的一門所見即所得的語言。你寫了一個屬性它就有一個樣式,就好比嗑瓜子,你每嗑一下都能及時的得到一個獎勵。這種愉悅感是別的開發語言所不具備的。

CSS 也不像其它側重邏輯的語言,有比較多的程式碼管理方式。你能管理 CSS 的工具只有兩個,一個是檔案引用,另一個是命名。通常為了減少頁面 HTTP 的請求,我們會盡可能的將 CSS 檔案合併。於是靠檔案引用這個方式來管理 CSS 的這條路也就顯得特別的窄了。

我們都知道 CSS 的作用域是全域性的,只要你引用了一個 CSS 檔案,它就會影響你整個頁面。於是,CSS 程式碼管理的重任就全壓在了命名這一條路上。

所以簡單的說,你能搞定 CSS 的命名,就能管理好 CSS。

管理 CSS 就好比管理“內褲”

如何管理 CSS “內褲”

對於 CSS 的管理,我這邊舉個不恰當但是很貼切的類比,就是類似於日常生活中內褲的管理,是的就是日常穿的內褲,和 CSS 中的“類庫”諧音(我太有才了)。

前面有講到,對於 CSS 的管理我們基本只能通過命名的方式去管理。這聽起來似乎是一件值得開心的事,因為只有一條路,所以大家都沒得選。然而出乎我們意料的是,即使只有一條路,大家也是走得五花八門。

舉個例子,比如我們有 7 條不一樣的內褲,如果只用命名的方式去管理內褲,會出現多少種可能?

按日期 按顏色 按材質 按花紋 ...
.星期一{} .紅色{} .純棉{} .格子{} ...
.星期二{} .黃色{} .滌綸{} .橫條紋{} ...
.星期三{} .藍色{} .氨綸{} .波點{} ...
... ... ... ... ...

就像一千個讀者就有一千個哈姆雷特一樣,不同的人對於同一件事物的命名方式是不一樣的。因為對於自己喜歡和熟悉的東西,對於其它的人來說都基本上是不熟悉的。不信你可以問問你的同事,你們歸納和命名內褲的方式很大概率是不一樣的。所以這個的可能性是無限的。

當然如果只有 7 條內褲,你和我的命名方式不一樣就不一樣唄,我只要能看懂基本也就還好。可是,當我們對於內褲的管理上升到了的概念的時候,一切就沒有那麼容易了。

假設你爸是挖礦的,你家很有錢。而你又特別喜歡買內褲,赤,橙,黃,綠,青,藍,紫,彩色的,蕾絲的,莫代爾的,純棉的,緊身的... 各式各樣的內褲共計 100 ,請問你要怎麼命名這 100 條內褲?

此時你會發現上面管理 7 條內褲的方式,任意一個方式都顯得力不從心。所以要怎麼辦呢?

管理 CSS “內褲” 的通用方法

之前有講到,管理 CSS 的問題就是 CSS 命名的問題。所以我們看看目前現有的最流行的解決 CSS 命名的通用解決方案 BEM。

如何管理 CSS “內褲”

因為我不是 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 能被大家看到。當然個人能力有限,如果不恰當的地方可以給我留言,我們一起探討。

內褲是工業品不是藝術品

到這裡可能有的同學會說,你這個原材料拆分的明顯沒對,布型別不是還有竹炭纖維,甚至太空材料的,顏色還有紅藍漸變或者五彩斑斕的黑。

對於我們大多數男性程式設計師來說,內褲無非就是棉的和不是棉的兩種,顏色無非就是黑,白,灰。即使不是程式設計師,你也很難會發現,普通的人會買到,赤,橙,黃,綠,青,藍,紫這麼多種顏色的內褲。

舉這個例子是想說明什麼,內褲是工業品而不是藝術品。工業品註定會控制原材料的種類以降低成本的。而真正會把內褲當藝術品的人,也就不會因為沒錢,而不會去考慮複用內褲的問題。

在我們網頁的開發也是一樣的,如果你的網站不是走藝術類的網站,你卻發現你的原材料提供商(設計師),光是從顏色上就給你提供了超過了十幾二十幾種顏色,那他一定是有問題的。

如果你的設計師,是對自己的設計語言是有極致約束能力的,那對於我們開發者來說這真的是一件非常開心的事情。

相關閱讀

  1. quickLayout.css-快速構建結構相容的web頁面 @張鑫旭
    男神作品,強推;
  2. 「英」在元件化浪潮中重新思考CSS @johnpolacek
    雖然是英文,但是網頁做得像PPT一樣,通俗易懂,強推;
  3. 「CSS思維」元件化VS原子化 @ziven27
    我的一篇專門解釋“元件化思維” 和 “原子化思維” 區別的文章;
  4. ACSS 官網 @雅虎
    這個思維最早應該是雅虎推出來的,最近他們有在推 React ACSS
  5. 關於HTML語義和前端架構 @大漠;
  6. 「譯」CSS通用類和“關注點分離” @adamwathan;
  7. 「英」Styling React @SURVIVEJS;
  8. 「英」CSS最佳實踐探討 - Atomic CSS @smashingmagazine;

“”

相關文章