我的 CSS 就是這么可愛——如何組織 CSS
本文轉(zhuǎn)載自微信公眾號「微醫(yī)大前端技術(shù)」,作者許浩星 。轉(zhuǎn)載本文請聯(lián)系微醫(yī)大前端技術(shù)公眾號。
寫在前面
開局先問大家一個問題:前端三劍客分別是誰?
不用說,絕大部分前端開發(fā)都會脫口而出:HTML、CSS 和 JavaScript。要是這個還需要猶豫的話,朋友自己去墻角反省一下自己[手動狗頭]。既然被稱為三劍客,那么就意味著這三者在前端開發(fā)中起到了重要的作用。HTML 負責頁面結(jié)構(gòu)的搭建,CSS 負責頁面的布局與美化,而 JS 負責的是賦予靜態(tài)頁面以動態(tài)的邏輯。從這個角度來看,這三者真的是缺一不可。但是隨著業(yè)務(wù)需求的緊逼,我們往往做不到“雨露均沾”,有意無意得忽略了某個角色——CSS。
就比如我自己,在日常的業(yè)務(wù)開發(fā)中,就經(jīng)常將注意力放在了 HTML 結(jié)構(gòu)和 JS 邏輯上,對于 CSS 就冷淡了很多。這樣子造成的后果就是當頁面的交互豐富、樣式多樣的時候,我們寫的 CSS 代碼行數(shù)多的嚇人,而且再也不想再看第二遍。用高情商的話說就是,我們寫的 CSS 代碼讓后續(xù)的開發(fā)者維護起來很有挑戰(zhàn)性。
靜下心來,我仔細地剖析了一下原因,發(fā)現(xiàn)主要是因為樣式代碼的穩(wěn)定性高。寫完了一遍 CSS,以后基本不可能再要修改了。這種“一次性”很難不讓人帶著一點糊弄的“心態(tài)”去開發(fā),然后留下一堆爛攤子給后面的同事罵人??。
但是!天道好輪回!如果碰到了需要去修改別人寫過的 CSS 樣式,那么這就是噩夢??。很難不讓人改的懷疑人生,最后選擇重寫一遍(嗚嗚嗚,別罵了,別罵了)!在碰到過這種情況后,我意識到我們需要從一個整體的角度來指導(dǎo) CSS 書寫,從而讓樣式文件變得更加美麗!這也是我寫這篇文章的初衷。
一、CSS 與審美
??審美是主觀的,它受到各方面因素的影響,例如文化背景,知識體系和性格愛好等等。我們作為前端開發(fā),在編程這個領(lǐng)域內(nèi)更是經(jīng)常與審美打交道。有時候我們經(jīng)常說某某代碼寫的垃圾,看半天也看不懂。某某大佬代碼寫的強無敵,條理清晰和邏輯完備。這些對于代碼的評價就是我們對于審美認知的體現(xiàn)。
??CSS 的存在就是賦予頁面美麗,如下面動圖所示:
上面的動圖我想每一位用戶都更喜歡加了 CSS 文件之后的頁面吧,因為符合人的審美。
既然 CSS 能夠讓頁面更加漂亮,那么對于 CSS 本身,我們更應(yīng)該讓它美起來!
二、什么樣的 CSS 是受人喜歡的?
??前面我們已經(jīng)找到了我們的目的:讓 CSS 更加好看!那么好看的目的是什么呢?是讓人喜歡。讓我們在需求開發(fā)時不抗拒去修改原有的代碼。那么這就引出了一個問題:什么樣的代碼讓人抗拒去修改?我們看看下面的兩種 CSS 代碼:
個人來說,第一眼看上去,左邊的代碼“擠”在一起,顯得亂糟糟的。而右邊的代碼更為清晰,每塊之間還有空行,讓人感覺更為舒服。那么問題來了,為什么右邊的代碼會讓我看上去舒服點?我在仔細比較這兩塊代碼的區(qū)別之后,我找到了答案:
每塊代碼之間間隔有序,不至于給人一個無比龐大的概念。
層級控制不超過 3 層,避免了過多嵌套層級“惡心”人
遵循了 BEM 命名規(guī)范,潛在的傳遞了關(guān)于元素之間的層級關(guān)系
??總結(jié)起來就是:將代碼的邏輯關(guān)注點分割個多個開發(fā)者可以輕易消化的小塊,同時做到一定意義的自解釋。這樣的處理減少了人腦需要處理這些代碼邏輯的難度,自然會給人舒服的感覺!
那么我們下面思考的更加深入點,抽象出 CSS 的書寫原則。
三、CSS 的一些書寫原則
??CSS 本身是沒有什么內(nèi)置的組織方式的,并且有各種書寫的方式,例如:內(nèi)聯(lián)和外鏈等等。所以我們需要自己完成建立編寫 CSS 時維持統(tǒng)一性和規(guī)則性的工作。Web 社區(qū)也已經(jīng)存在了多種工具和方法,來幫助開發(fā)者管理大的 CSS 項目。我們可以借鑒并調(diào)整為適合我們自己的書寫方式。但在這之前,我們需要明確幾個 CSS 書寫原則。
- 少即是多
- 自解釋
- 可復(fù)用
??上面 3 條原則是我在開發(fā)過程中自己總結(jié)出來的,如果大家有更多的想法??,歡迎和我一起探討。先說說第一條原則:少即是多(Less is more)。這句話的英文版本是建筑師凡德羅在建筑領(lǐng)域提出的觀點。他反對機械化生產(chǎn)的產(chǎn)品中存在的繁復(fù)的無意義的裝飾。這同樣也適用于 CSS 的編寫中。在前端三劍客中,HTML 是結(jié)構(gòu),JS 是行為,CSS 則是表現(xiàn)。換句話說,CSS 的作用是裝飾頁面。在這個前提下,去除那些冗余繁復(fù)的 CSS 代碼不僅能減小瀏覽器的性能消耗,還能讓開發(fā)者更加深入的思考表現(xiàn)與結(jié)構(gòu)之間的關(guān)系。我認為這對于前端開發(fā)工程師的思維成長是有幫助的。
- // 存在多余的代碼
- .footer {
- margin-top: 30px;
- margin-bottom: 20px;
- }
- // 優(yōu)化
- .footer {
- margin: 30px 0 20px 0;
- }
上面的代碼就是最簡單的少即是多的實踐,但不僅限于此。我們更需要從整體上進行思考與實踐。那么如何做到這一點呢?無它,惟手熟爾。所以每次開發(fā)中,都要記住我們的口號:“絕不多寫一行 CSS!”。
第 2 條原則自解釋的意思是 CSS 的書寫要盡量說明自己是干什么的,減少額外的注釋代碼。
- // 存在模糊地方
- .footer:first-child {
- color: #FFF;
- font-size: 18px;
- }
- // .footer-title {
- color: #FFF;
- font-size: 18px;
- }
上面的代碼解釋了這個元素的目的,是 footer 部分中關(guān)于 title 的文本。這樣可以讓我們很容易定位到對應(yīng)的 html 元素,從而進行樣式的修改。對于這條原則的實現(xiàn),社區(qū)已經(jīng)有了一套很完善的方案:BEM 命名。這套規(guī)范即避免了不同文件下的命名沖突,還很好的賦予了 CSS 類名的語義化。讓我們的腦子對于 CSS 那種模糊的印象變得條理清晰。
- <div class="person-center__wrap">
- <div class="person-center__main">
- <div class="userInfo-name">
- 王狗蛋
- </div>
- <div class="userinfo-age">
- 24
- </div>
- </div>
- <div class="person-center__footer">
- <div class="sctions-comfirm">
- 確定
- </div>
- </div>
- </div>
上面這段代碼就較好的使用 BEM 命名將額外的頁面結(jié)構(gòu)信息塞到了 CSS 類名上了,讓開發(fā)者不至于摸不清 CSS 的對應(yīng) DOM 結(jié)構(gòu)。再配上預(yù)處理語言 SASS 等,更加從心智上將消除了 CSS 的信息缺少與模糊性,保證了頁面結(jié)構(gòu)、表現(xiàn)和行為的統(tǒng)一性。
最后一條可復(fù)用的原則就不多說了,懂得都懂。這條原則的基礎(chǔ)是 CSS 預(yù)處理語言的使用。因為 CSS 本身是一種描述語言,本身是沒有邏輯的。但是隨著業(yè)務(wù)的越來越復(fù)雜,我們渴望將邏輯代碼加入 CSS 中。這也是 SASS 預(yù)處理語言興起的原因之一。加入邏輯的 CSS 預(yù)處理語言中,我們可以定義變量、使用循環(huán)和條件判斷,從而復(fù)用 CSS 代碼。
四、保持 CSS 整潔的技巧
在了解了書寫 CSS 的原則之后,我們還需要在實踐中運用它們。在這個過程,一些保持 CSS 整潔的技巧對我們實踐是很有幫助的。
1. 確定項目的代碼規(guī)范
??在和多人進行項目的開發(fā)時,第一時間需要檢查該項目是否有了 CSS 的代碼規(guī)范。遵循項目的代碼規(guī)范進行開發(fā),是保持 CSS 整潔的基礎(chǔ),也是不讓別人吐槽的護盾。如果你的個人喜好跟規(guī)范相沖突,那么還是請遵守規(guī)范,因為別人或許不喜歡你的風格。
2. 保持統(tǒng)一
??當你開始進行需求開發(fā)并書寫 CSS 代碼時,最重要的是保持各方面的統(tǒng)一。例如之前的代碼使用的是 rem 單位,并且在代碼開頭進行了換算和變量定義。那么你需要做的就是跟隨!!而不是標新立異的使用另一套自己的方式。
統(tǒng)一在所有的地方都會起到實際作用,例如對類使用相同的命名常規(guī),選擇一種描述顏色的方式,或者維護一個統(tǒng)一的格式化方式(例如你是使用 Tab 還是空格來縮進代碼?如果是代碼,用多少個?)
一直遵守一系列規(guī)則,你會在編寫 CSS 的時候省去不少精神上的預(yù)負擔,因為一些決定已經(jīng)定型了。要知道代碼是寫給人看的,順帶著可以在機器上運行。在這里給我們團隊的開發(fā)規(guī)范打個廣告:微醫(yī)前端開發(fā)手冊 1.1(修訂中),歡迎大家提出意見,共同進步。
3. 將 CSS 格式化成可讀的形式
你可以看到很多 CSS 格式化的方式,一些開發(fā)者將所有的規(guī)則放在一行里面,像是這樣:
- .box { background-color: #567895; }
- h2 { background-color: black; color: white; }
??還有的開發(fā)者更喜歡將所有的東西放在新的一行,并且不同元素之間空行:
- .person-center {
- &-wrap {
- width: 100%;
- }
- &-main {
- color: #FFF;
- font-size: 16px;
- font-weight: 500;
- }
- }
??CSS 不會管你使用哪種方式來進行格式化,我的看法是在遵循代碼規(guī)范的前提下讓 CSS 代碼更加具有可讀性。保證了你自己還愿意下次看,才能保證其他開發(fā)者能夠看的下去你的代碼。
4. 為你的 CSS 加上注釋
代碼自解釋為前提,但是在某些定制需求時需要加上注釋,表明相關(guān)業(yè)務(wù)背景和其他信息。這樣做不僅可以幫任何未來的開發(fā)者處理你的 CSS 文件,也可以在你離開項目一段時間后,幫你在回來時重新上手。
- /* 這是一條 CSS 注釋,
- 它可以分成好幾行。*/
在你的樣式表里面的邏輯段落之間,加入一塊注釋,是個好技巧。在你快速掠過的時候,這些注釋可以幫你快速定位不同的段落,甚至給了你搜索或者跳轉(zhuǎn)到那段 CSS 的關(guān)鍵詞。如果你使用了一個不存在于代碼里面的字符串,你可以從段落到段落間跳轉(zhuǎn),只需要搜索一下,下面我們用的是||。
- /* || General styles */
- ...
- /* || Typography */
- ...
- /* || Header and Main Navigation */
- ...
或許你是照著一個社區(qū)教程來做事的,CSS 有些不夠直觀。此時,你應(yīng)該在注釋里面加入教程的 URL。你應(yīng)該在你一年或者更長時間以后重新審視你的項目,但只是模模糊糊地想起來之前有個優(yōu)秀的教程,不知道它在哪里的時候,感謝之前加入注釋的自己。
5. 在你的樣式表里面加上邏輯段落
??在樣式表里面先給一般的東西加上樣式是個好想法。這也就是除了你想特定對某個元素做點什么以外,所有將會廣泛生效的樣式。典型地,你可以為以下的元素設(shè)定規(guī)則:
- body
- p
- h1, h2, h3, h4, h5
- ul 和 ol
- table 屬性
- 鏈接
在這段樣式表里面,我們提供了用于站點類型的默認樣式,為數(shù)據(jù)表格、列表等設(shè)立了一份默認的樣式。
- /* || GENERAL STYLES */
- body { ... }
- h1, h2, h3, h4 { ... }
- ul { ... }
- blockquote { ... }
??在這段之后,我們可以定義一些實用類,例如一個用來移除默認列表樣式的類,我們打算將其展示為靈活樣式或者其他樣式。如果你知道你想要在許多不同的元素上應(yīng)用的東西,那么你可以把它們加到這里。
- /* || UTILITIES */
- .nobullets {
- list-style: none;
- margin: 0;
- padding: 0;
- }
- ...
然后我們可以加上在整個站點都會用到的所有東西,這可能是像基礎(chǔ)頁面布局、抬頭或者導(dǎo)航欄樣式之類的東西。
- /* || SITEWIDE */
- .main-nav { ... }
- .logo { ... }
最后我們可以在 CSS 里面加上特指的東西,將它們分成上下文、頁面甚至它們使用的組件。
- /* || STORE PAGES */
- .product-listing { ... }
- .product-box { ... }
通過使用這種方式排布代碼,我們至少能大致了解,我們能在樣式表的哪個部分尋找想要更改的東西。
6. 避免太特定的選擇器
如果你創(chuàng)建了很特定的選擇器,你經(jīng)常會發(fā)現(xiàn),你需要在你的 CSS 中復(fù)用一塊代碼,以將同樣的規(guī)則應(yīng)用到其他元素上。例如,你也許會有像是下面的選擇器那樣的代碼,它在帶有main類的
上應(yīng)用了規(guī)則。 如果你之后想要在main外的什么地方上應(yīng)用相同的規(guī)則,或者在 外的其他地方,你可能必須在這些規(guī)則中加入另一個選擇器,或者直接新建個規(guī)則?;蛘撸阋部梢越⒁粋€名為box的類,在任何地方應(yīng)用。 將東西設(shè)置的更為特定,有時也有意義,但是這一般與其說是通常實踐,倒不如說是例外。 這個技巧可以說是我們已經(jīng)做到很好了。一般項目中都會有一個 styles,里面存儲一些全局共用的樣式文件。根據(jù)這些文件的作用,一般又會被細分為reset.csss、variables.less等文件。搭配上預(yù)處理語言的 mixin 功能,我們就可以維護一份常用的樣式文件,避免在具體的頁面書寫冗雜的 CSS 代碼。 這可以讓你更容易保持 CSS 的組織性,也意味著如果有多人在寫 CSS,你會更少遇到有兩個人需要同時編寫相同的樣式表的情況,防止在源代碼的控制上產(chǎn)生沖突。 人區(qū)別于大猩猩的一處就是善于使用工具解決我們遇到的困難。身處于互聯(lián)網(wǎng)的浪潮中,我們更應(yīng)該擁抱那些有幫助的工具??。使用 stylelint + githook 來規(guī)范我們的 CSS 代碼,使用 Less/Sass 預(yù)處理語言讓 CSS 更加有“邏輯” 。它們解放了我們的大腦,也在潛移默化中培養(yǎng)我們的編碼規(guī)范。 沒有人是完美的,人的一個優(yōu)勢就是可以通過學(xué)習來提升自己。那么我們作為程序員,更需要與厲害的同行交流經(jīng)驗,學(xué)習別人好的編碼規(guī)范融入自己的日常開發(fā)中。每個人都是獨立的個體,每個人也都有著自己的想法,身處于這行,開放思想,用于承認自己的不足,才是能夠永遠進步的源泉!! ??這包括了線下團隊之間開展專題討論和線上參與社區(qū)討論等等措施,多與人溝通才能開拓我們的技術(shù)視野。 原諒我在最后的小結(jié)起了一個很文藝的標題。我最近在看一部蠻老的日?。骸洱垯选罚瑒≈心兄靼⒉繉捀鷤淇紪|大的幾個“笨蛋”說考試是一場與自己的對話,也是一場與競爭對手的對話。 走上職場的我們,無論是初入職場的激情滿滿還是磨練了幾年后的波動如山,限制著影響著我們的只有自己。但是信息繭房不僅封閉了我們對外界的認知,更剝奪了我們對自己的認知。 將時間尺度拉到,拉到 1 年、3 年、5 年乃至 10 年。你寫的代碼作為時間的錨點一直存在于那里,這又不是一種另類的未來與現(xiàn)在的對話嗎?所以如何組織 CSS 呢?第一原則就是當成與自己的對話,做到你不嫌棄自己。在這基礎(chǔ)上,掌握并找到適合自己的編碼原則,使用規(guī)范和工具來糾正監(jiān)督自己,剩下的就是實踐 => 修改 => 再實踐 => 再修改的無限循環(huán)。 整潔的代碼是由整潔的人寫出來的,寫出可愛的代碼也一定是個可愛的人。我最開始寫代碼的理想的想通過虛擬世界來幫助我理解現(xiàn)實世界的復(fù)雜性。我們在將復(fù)雜、錯亂的 CSS 代碼進化為整潔、邏輯關(guān)注點清晰的代碼。這一過程同時也是一場與自己的對話,問自己喜歡什么,問自己想要什么。在這種潛意識的一個個疑問中,我們整理著內(nèi)心。 我們在 0 和 1 的世界里,思考著物理世界的喜怒哀樂,希望朋友們能夠撇去浮燥世界帶來的浮沫,都能找到生活的真諦!畢竟努力工作只是手段,我們的目標是未來的幸??鞓飞?諸君共勉!7. 分割大樣式表為多個小樣式表
8.善用工具
9. 學(xué)習與模仿
五、寫代碼是與自己的對話