寫CSS簡單,但寫出可維護(hù)的CSS卻很難。
這句話你可能早已聽了上百遍。之所以說CSS代碼難以維護(hù),因?yàn)樵贑SS中所有的成員都是全局的。如果你是一名C語言程序員,你應(yīng)該清楚全局變量的壞處。而只要是程序員就該知道隔離和可組合的模塊是搭建可維護(hù)系統(tǒng)的關(guān)鍵所在。
有多CSS的風(fēng)格指南被創(chuàng)建出來用于指導(dǎo)人們寫出可維護(hù)的CSS代碼,SMACSS, OOCSS, BEM, ITCSS, ACSS, CCSS, Atomic Design, Maintanable CSS, rscss, 以及更多
那么,問題出在哪兒呢?
span {
font-size: 11px;
}
.header-right {
font-size: 22px;
text-align: right;
}
上面CSS代碼聲明的樣式作為全局成員,將會(huì)影響到所有頁面中的span和class為header-right的元素。沒有封裝,也沒有隔離了的模塊。
在標(biāo)準(zhǔn)的編程語言中,你只需要引入需要的模塊來完成特定的功能。
# Python modules
import requests
from Flask import ur
// Node modules
var express = require(‘express’)
采用這種形式,你能夠準(zhǔn)確地知道什么將會(huì)影響你的代碼,因?yàn)闀?huì)對(duì)你正在實(shí)現(xiàn)的功能產(chǎn)生影響的只有你顯示引入的模塊。
然而在CSS中,情況反了過來。每當(dāng)我寫出一行CSS代碼,都可能潛在地影響項(xiàng)目中的其他部分,除了我正著手修改的頁面,其他頁面的外觀也可能被意外地改變。泄露已不足以形容CSS樣式對(duì)我整個(gè)應(yīng)用帶來的影響,這些樣式如洪水一般滲入到應(yīng)用的每個(gè)角落。
這其實(shí)是可以理解的,特別是對(duì)一些基本的樣式如印刷格式、簡單的表單輸入框樣式以及天生就應(yīng)該是全局的樣式,采用這種方式是有意義的。HTML和CSS一開始本來為出版而生。為了能更好的理解隱藏在這兩門語言本后的思想,我常常會(huì)設(shè)想對(duì)一本書進(jìn)行排版,你會(huì)希望書中的每一頁都看上去不一樣嗎——當(dāng)然不會(huì),你要的是簡單且統(tǒng)一的風(fēng)格,不是花里胡哨的東西。所以會(huì)有<H1>到<H6>,<section>等標(biāo)簽,和一直存在的全局樣式。
然而,世界在改變,WEB也在跟著在變。我們創(chuàng)建的不再是網(wǎng)頁,而是網(wǎng)頁應(yīng)用。HTML和CSS為出版而生的說法已不再適用于今天的WEB了。
我們需要新的方法來指定樣式,或者新的方法來搭建WEB程序。不過現(xiàn)在我們?nèi)匀恍枰狧TML和CSS, 這意味著我們需要謹(jǐn)慎的對(duì)待它們,以一種能創(chuàng)建出可管理和可維護(hù)的web應(yīng)用的方式。
Peergrade.io處理CSS的方式
為class名稱提供前綴
在Peergrade.io,我們所有的class都有.pg前綴。在CSS代碼中不使用前綴是自找麻煩,原因是沒有前綴的樣式名稱最終會(huì)和導(dǎo)入的樣式發(fā)生沖突。比方說你需要一個(gè)datepicker, 你當(dāng)然不會(huì)想自己從頭寫一個(gè),所以你選擇導(dǎo)入第三方代碼。現(xiàn)在你向代碼里導(dǎo)入了.prev, .next和.separator等樣式聲明,如果你沒有為你自己聲明的樣式使用前綴,沖突隨時(shí)都可能發(fā)生。
不要嵌套選擇器
在Peergrade.io我們使用Sass,使用Sass,你的樣式聲明結(jié)構(gòu)很快就會(huì)變得和你的HTML結(jié)構(gòu)一致。就像下面一樣:
#user-profile-page
.profile-description
h3
ul
li
a
一段時(shí)間以后,你可能感覺還不錯(cuò),但終會(huì)意識(shí)到這種樣式結(jié)構(gòu)是多么的脆弱。一開始,你或許認(rèn)為在.profile-description
下只會(huì)有一個(gè)列表,但一兩個(gè)月之后你才意識(shí)到下面還會(huì)有其他的列表,很快樣式結(jié)構(gòu)就會(huì)打破你的一系列假設(shè)。
另外,這樣的聲明方式會(huì)將樣式應(yīng)用于父元素下的所有子元素,而不是按結(jié)構(gòu)層級(jí)一一對(duì)應(yīng)的方式。
為組件使用BEM命名方式
采用BEM的命名方式為class命名,盡可能創(chuàng)建可隔離的組件。我們并沒有完全遵循BEM指南——只是采用了其命名方式,形式如下:
.block__element--modifier
在Sass中,我們是這樣做的
.pg-deadline
&__date
// becomes `.pg-deadline__date`
color: $color-gray
&__header
// becomes `.pg-deadline__header`
font-weight: 700
&--highlight
// becomes `.pg-deadline__header--highlight`
color: $color-green
在Sass中,我們采用嵌套的方式創(chuàng)建了遵守BEM的樣式聲明,雖然有點(diǎn)違反直覺,但編譯過后會(huì)生成沒有嵌套結(jié)構(gòu)的CSS代碼,全是頂級(jí)的樣式聲明。
作為第二條規(guī)則的例外,我們?cè)试Sclass名稱采用.block-modifier形式。
.pg-deadline--editable
.pg-deadline__header
background-color: $color-blue
.pg-deadline__date
color: $color-black
在這個(gè)特殊例子中,我們?cè)试S存在一層CSS選擇器嵌套。這使得我們只能為塊(block)指定修飾器(modifier),從而不用為塊(block)的每一個(gè)子元素(BEM中的E)指定修飾器(modifier)。
想要更好的了解BEM的命名方式,可以參考Harry Roberts的CSS指南中BEM命名方式部分
向前看
似乎至今還沒有人真正找到一種方式可以很好的處理CSS(Hacker News上的相關(guān)文章),但至少,我們相信我們找到了一種可持續(xù)發(fā)展的基礎(chǔ)——盡管還有可改善的空間。
原文鏈接:https://medium.com/peergrade-io/structuring-css-in-large-projects-37f1695f5ec8