精简高效的CSS命名准则/方法
2019獨角獸企業重金招聘Python工程師標準>>>
一、“無”的哲學
佛家講究“因果報應”,有果必有應。此段看似與主題沒有血緣關系,實際講的是“因”。
我個人比較喜歡老子的道家思想,并喜歡以其思想解釋學習與工作中遇到的一些問題。例如我之前寫過的“中國古代道家思想與網頁重構的思考”一文。
老子有云:“天下萬物生于有,有生于無”。具體解釋就是:天下萬物都是由看得見的具體事物(“有”)產生的,而看得見的具體事物(“有”)又是由看不見的,無形無狀的東西(“無”)產生的,這個看不見的“無”也就是“道”,或叫做“根”、“母”。
我們看武俠片,經常聽到“無招勝有招”這句話,這也是道家“無”之思想之體現。因為你心中沒有招式,你才能有無限的可能,生成其他的招式以克敵,即所謂以不變應萬變;相反,如果你心中牢記一套“華山劍法”,當你與人交手時,勢必按照此套路走,要是遇到相克之劍法,結局就是一敗涂地。“無招”是一種境界,是你功夫修煉到一定程度才能領悟到的。我們這代人應該都看過李連杰主演的《倚天屠龍記魔教教主》,其中張三豐老頭教完張無忌太極拳后問他“記住了沒?”張無忌一句“全忘記了!”讓人印象深刻。這就是“無”的境界。
這種境界我是深有體會的。例如每逢大考之前,我總是把以前做過的題目全部忘掉,這樣,考試時就能思如泉涌;反而是強記題目的做法限制了發揮。這就好比發射炮彈,炮管里提前預裝了重型炸蛋,結果戰斗開始時,發現需要的是煙霧彈,此時,反而被預裝的炸蛋給阻塞限制了。打籃球也有這種體會,如果心中記得的是動作,我要這么走,然后這么做,往往表現不佳。反而是腦中什么想法也沒有,全靠下意識行動,那真是所向披靡,得分如探囊取物。
可見,要想發揮更大,就需要“無”,把一些“限制的東西”通通去掉。沒有限制才能發揮出最大的潛能。站在最簡單,最原始的那個點上,你才能自由馳騁,應變自如。
二、名字的本質是什么
我們有沒有思考過這么一個問題:名字的本質是什么?
這個問題其實不難,名字本質上就是一個符號,用來區分人與人的。與符號一樣,名字本身就蘊含著很多的信息。舉個例子,我的名字:張鑫旭。其中蘊含的信息有:我老爸也姓張,我是上午太陽剛剛升起的時候出生的,我五行缺金。一個名字,如果其蘊含的信息越多,則這個名字就越獨特,也就是說,越不可能被別人使用;相反如果這個名字很普通,例如李娜、張艷之類,就會被大規模的重用,OK,這其實沒什么大不了的,我們的唯一身份標識不是名字,而是身份證,但是,對于CSS樣式的命名,沖突與否可不是拉便便,擦個屁股就沒事的。
對于CSS,為了避免樣式沖突,我們總會給其賦予相當特殊的命名,或是在選擇符上添加HTML標記,或是使用層級。所謂一朝怕蛇咬,十年怕井繩。一旦我們經歷過樣式沖突帶來的讓人吐血的麻煩后,我們可能就會時時在避免沖突上狠做文章,所謂過猶不及,結果又是一個爛攤子,本如花似玉的黃花小閨女變成個臃腫的肥妞。例如下面人人網的CSS命名:
我想我們都希望寫出精簡高效的CSS代碼,如果CSS重用性越高,想必就越高效。這如人的名字一樣,如果名字越普通,越沒有含義,越容易被重用,所以CSS要想重用性高,就需要命名簡單。但是,簡單的命名越容易造成樣式沖突,例如.more{}。從這點上來說,重用性與樣式沖突時兩個對立的矛盾體。
不過,萬幸的是,這種矛盾并不是不可調和的。記住一些準則/方法,CSS既可以有高度的重用性,又不會有樣式沖突的困擾。下面就將介紹這些命名方法。
三、面向屬性的命名方法
我們習慣在CSS命名的時候摻雜語義,這樣可以讓代碼更易懂。例如淘寶首頁“免費注冊”按鈕上的class名稱:help-guest-regist
上面的class命名語義就很明顯,獨眼龍看告示——一目了然,”help-guest-regist”就是”幫助-顧客-注冊”,很nice,很人性化的命名。作為在單一的首頁上使用,我是很難挑出什么毛病來的。
但是,從道家“無”的哲學思想來看,語義其實是對自身的一種束縛,越是語義強烈的命名越是沒有重用性(尤其是內容語義的)。舉個實際點的例子,例如人人網的右側邊欄的標題://zxx:一般找這類反例我就喜歡找人人網還有新浪,基本上一找一個準。人人網雖然外表長得跟facebook類似,但是就CSS而言,差距不是一兩個檔次的。
這個標題的class名是”side-item-header”,樣式如下圖所示:
現在一切ok,現在設想下,如果頁面中間的模塊有個標題,其樣式也是:
{padding:0 0 8px; text-align:right;}那你發現前面已經有一模一樣的CSS樣式后,你會怎么辦。把中間的標題也用”side-item-header”這個class嗎?這里”side”就是表示“邊”的意思,這就意味著這個樣式用在非側邊欄就是不合理的。你能做的估計即使新命名一個class,就像是”body-item-header”,明明是同樣的CSS屬性,結果卻不能重用(即使使用標識符組合并CSS,這里的命名也是沒有重用的)。
可見命名不合理會大大限制你的CSS重用性。如何命名才能讓CSS發揮最大的重用性潛力呢?答案就是“面向屬性的命名”。這種命名就是要讓你把頁面啊設計啊什么的通通塞到馬桶里沖走,不要管頁面什么位置,什么內容,there is noting, 這兒什么都沒有,既然什么都沒有,也就沒有了任何限制,于是CSS可以自由出入于任何地方,無限重用,而且不用擔心沖突,因為“面向屬性的命名”就是針對自身屬性的一種命名方式,只會overwrite,不會沖突。
相比很多同行都用過這樣的命名方式,只是不夠系統,不夠大膽、徹底,多淺嘗輒止,比如像是開心網,還有時光網的CSS代碼的前面一部分樣式命名:
我在“CSS樣式分離之再分離”一文中就展示過這種命名了,分離為什么可以讓樣式的重用性放大至最大,就是因為分離后樣式的命名就是樣式本身。
就拿上面人人網的標題樣式舉例,人人網的做法是:
.side-item-header{padding:0 0 8px; text-align:right;}要是我,我會對其進行分離。在實際項目時,text-align:right;這個屬性早就在CSS通用樣式庫里面了,而padding:0 0 8px;則會以padding-bottom:8px;的形式放在網站通用樣式庫里了(詳細請參見我的“我是如何對網站CSS進行架構的”一文)。最后,CSS命名與樣式會如下:
.tr{text-align:right;} .pb8{padding-bottom:8px;}而這里分離出來的樣式又可以被其他地方使用。是不是有點“吸星大法”的感覺。
當然,如果網站本身的架構不是對每個側欄內容進行模塊化處理的話,說實話,這里標題的分離還是有點危險的。想想看,如果那天產品經理說底部padding值要改成10像素,啊哦,如果你的網站架構不合理,含這類標題的模塊到處塞,會改到你急火攻心,吐血三升而亡的。所以,對于分離,我反復強調,“千萬不要對網站通用的元素進行分離”。
所以,記住精簡高效的CSS命名準則之一:對于網站非通用元素,如果樣式簡單(1~2個屬性),對其分離并使用面向屬性的命名方法。
四、精簡高效CSS命名之“三無原則”
此“三無原則”就是:無ID,無層級,無標簽
CSS命名就應該最簡單、最直接,直搗黃龍。沒有HTML標簽,沒有層級,這些通通滾蛋,不要。為什么不要,有三大原因:
1. 限制重用
我們會使用層級(#test .test),會使用標簽(ul.test),可能是習慣(沒多想),或是為了避免沖突。但是,我跟你說,從今以后,這種寫法讓他見鬼去吧(如果不是為了改變CSS優先級的話)。正如開篇論述的哲學觀點,你限制越多,越抑制了CSS的重用性。例如#test .test{}這種寫法,里面的CSS重用性多大,完全限死在了id為test的元素下,哪有重用性可言;又如ul.test,我勒個去,這個ul標簽十有八九就是裝飾用的,往這兒一放,同樣CSS樣式的div標簽可以用嗎?哭爹喊娘,眼淚汪汪也不管用啊。所以,相信我,層級啊,標簽啊什么的,通通見鬼去吧。要知道,層級啊,標簽啊作用是什么,是用來提高CSS優先級,把那個字母長的讓人發毛的”!important”干掉的。
2. CSS文件大小
這瓜子雖小,吃多了也是可以填飽肚子的。所以,你的CSS名稱不要像老太太的裹腳布一樣,搞得又臭又長,如下圖所示的人人網那個冗長的CSS命名吧:
你看名稱的字節數已經比屬性還大了,要是這些名稱都在15字符以內,乖乖,這個CSS文件可以小個1~2K絕對沒有問題的。你看下圖這樣子的命名,這樣子的CSS排版是不是更舒服,更簡潔。
3. 降低了渲染效率
來個例子考考大家(以后我面試別人可能就會考這題),HTML如下:
現在要給這里的ul標簽一個樣式,比如說padding-left:25px;那么下面四種寫法哪個渲染速度最快?
#test .test{}, ul.test{},#test ul{} 以及.test{}。
如果單純的ul與.test PK,我還真拿不定誰的渲染速度更快些。但是,一旦牽扯到層級與標簽,我100%確定,.test這種最直接的命名方式渲染效率是最高的。要知道,CSS渲染元素和使用JavaScript獲取頁面元素那是完全不一樣的。如果是使用JavaScript獲取DOM元素,則#test ul{}速度是最快的,先id獲取,再tag獲取,這些可都是JavaScript內置的方法。但是,CSS的渲染方式則是屬于外太空系的了,《高性能網站進階指南》一書曾提到CSS的渲染方式是“從右往左”渲染的,就拿#test ul{}舉例,先渲染頁面上所有的ul標簽,再去尋找id為test的元素,所以,出現#test div{}這種寫法的人都是傻×的,頁面先渲染id為test的元素?非也!先渲染頁面上所有的div,再去尋找其老爸有沒有id為test的元素。由于這種渲染差異最大就200~300毫秒(補充:這里的差異不是說單純一個樣式的差異,而是這些寫法泛濫的頁面的全部渲染,其渲染差異數據可以參見“翻譯-不同CSS技術及其CSS性能”一文),我們人一般是感覺不到的。所以,長久以來,也都不以為然。但是,我是絕對容不下這種寫法的,還有,要是讓我看到類似于ul#test{}這樣子的命名,不好意思,面試肯定過不了。
所以,CSS命名,只要出現了層級,出現了標簽,就是一次額外的渲染,層級越多,渲染的開銷也就越大,這就是為什么一些前輩的文章會建議要盡量避免過深的層級。這也是為什么要“無層級”,“無標簽”。
對于原則第一條“無ID”,其實與性能沒有多大關系,只是一般ID都與JavaScript有奸情,如果再牽扯到CSS樣式,如此復雜的三角關系,日后不好處理啊。
五、“三無原則”遺留之樣式沖突問題
正如上面講的,層級,標簽可以避免樣式沖突,雖然“面向屬性的命名”不存在沖突問題,但是,頁面上很多樣式是無法分離使用“面向屬性的命名”的,此時,一不能有層級,二不能有標簽,如果避免沖突呢?
首先,規范。項目組所有人的命名方法,習慣都要統一。其次,也是實際的做法,同一內容,使用同一前綴。就如上面的那張圖片所示,所有class同一使用od前綴,這樣,就絕不會與其他頁面的CSS產生沖突了。
現在,還隱藏著一個會讓人心存疑惑的遺留問題。如下:
上圖中,很多個鏈接全部存放在一個標簽中,全部都是a標簽,按照我的“三無原則”,不能使用層級,那么,我這里的每個a標簽都得附一個.index_list_a{}這樣子的命名嗎,這樣子repeat下來,頁面HTML代碼豈不是很大,直接來個.index_list_box a{},豈不是頁面HTML更加清爽。確實有理。實際上,按照我個人實踐的經驗,這類細小重復的列表元素的樣式都是比較簡單的,不要忘了,精簡高效的CSS命名準則之一的“分離與面向屬性命名”,所以,對這里的a標簽進行面向屬性的命名,權衡后期的重用性和HTML代碼開銷,還是直接針對a標簽進行簡單命名是最佳解決方案。
但是,不排除這類最內層標簽且重復元素的樣式會很復雜,此時,使用層級與標簽,或許是更好的做法,但這只存在于一些非常特殊的情況。對了,我們看看點評網是如何對最內層且重復的a標簽進行處理的,如下圖:
點評網是使用的一個大寫的”B”作為此樣式,無論這里的”B”是有background之意,還是邪惡的***之意,其命名比“面向屬性命名”更甚一籌,可以說是接近真正意義上的nothing,后面可以跟任意屬性,用在任意頁面,這就是“無”哲學,“無”的境界。//zxx:點評網的這個命名讓我聞到了一點Google的氣息
六、結語
現在,來個簡短的總結,精簡高效的CSS命名的關鍵字有“分離”,“統一前綴”,方法為“面向屬性的命名”,準則為“無層級、無標簽”。其中,“分離”是“面向屬性命名”的基礎。“面向屬性命名”和“無層級、無標簽”屬于兩個不同的系列,一個針對短命名屬性,一個針對長命名屬性。但是,兩個又互相依存。沒有“面向屬性命名”,“無層級、無標簽”命名最后是以不堪重負,HTML膨脹致死結局。而僅僅是“面向屬性命名”,前端開發人員會因維護過勞噴血而死。總之,兩者缺一不可。
上述所有內容,都是根據自己的開發總結出來的東西,個人觀點,經驗之談。每個人的成長不同,工作環境不同,必然在看到一些問題上會有差異,歡迎交流與討論。我資歷尚淺,文中難免會有不準確的地方,歡迎指正。
我的這套準則是建立在自己的一套CSS架構上的,我自己用的是非常開心的,而且效果非常明顯。但是,到底是否適用于其他同行,我不能保證,畢竟優秀的前端人員心中都有自己的那一套準則。我的個人建議是這樣的,如果您還是個CSS新手,或者對我文中提到的一些概念不太理解,我覺得全搬過來不太合適。您可以保留您之前那種一步一趨的寫法,然后在這基礎上做您確定的改進。如果真能對您CSS的學習提供一些幫助與啟示,那真是再好不過了。
補充于2013-01-10
今天我看到一篇譯文,復雜應用的 CSS 性能分析和優化建議,原文地址:http://perfectionkills.com/profiling-css-for-fun-and-profit-optimization-notes/
其中提供了很好的證據說明,糟糕的命名對渲染性能造成的影響。
這是其中的測試圖:
可以看到,渲染性能最高的選擇器就是 .xxx a 這種形式是最好時的。這說明,“類名+標簽名”這種形式確實耗性能。本文可能戳中了不少自封人士的敏感神經,N多不屑,覺得這性能影響不值一提。OK,數據說話,以下為一段引用:
其實并不存在最快的規則,我們通常做法是把樣式模塊合并到一個文件中試用,這樣會導致其中的一部分樣式并沒有被特定的頁面用到。其實把沒用的樣式規則拿掉是優化 CSS 的最好的方法之一,因為這樣的話就可以省去多余的樣式匹配,當然合并多個文件到一個大文件還是有好處的,比如說可以減少請求數,但是我們應該只把跟當前頁面有關的樣式打包到一起。
其實這也不算什么新發現了,Page Speed 早就有過這條建議。不過,我還被它的效果嚇到了,去掉多余樣式讓我節省了大約?200-300ms?的選擇器匹配時間(根據Opera 調試工具的結果)。
200-300毫秒?你唬我吧!人家kangax大神可不會玩虛的~
很多網站CSS模塊都組隊放在一個CSS文件中,比方說你有10個CSS模塊,每個模塊都有一個.module_a a{} .module_b a{} ...的CSS命名,然后你訪問只有模塊C的頁面,結果如何?不要天真地以為這個頁面不管模塊a和模塊b的事情。正如文中所說的,CSS從右往左渲染,你的頁面是沒有.module_a?也沒有.module_b,到時你頁面有a標簽啊,a標簽大大的多哈!
于是,
.module_a a{}的時候,頁面上,所有的a標簽掃一遍;
.module_b a{}的時候,頁面上,所有的a標簽掃一遍;
.module_b c{}的時候,頁面上,所有的a標簽掃一遍,恩,這個有效果;
.module_b d{}的時候,頁面上,所有的a標簽掃一遍;
.
.
.
掃一遍只要0.3毫秒(如上截圖),你頁面要是有100個類似.xxx a{},那就是300毫秒的渲染,如果你現在還說“300毫秒的渲染差異我不在意”的話,我也不能說什么了!
轉載于:https://my.oschina.net/m2gIGj8g1iU/blog/809282
總結
以上是生活随笔為你收集整理的精简高效的CSS命名准则/方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 妖怪与和尚过河问题
- 下一篇: vs2015调试时无法显示QString