市面上我們常常會(huì)看到各種各樣的設(shè)計(jì)模式書(shū)籍,Java設(shè)計(jì)模式、C#設(shè)計(jì)模式、Ruby設(shè)計(jì)模式等等。在眾多的語(yǔ)言設(shè)計(jì)模式中我唯獨(dú)找不到關(guān)于 CSS設(shè)計(jì)模式的資料,即使在網(wǎng)上找到類(lèi)似內(nèi)容,細(xì)細(xì)一看之下才發(fā)覺(jué)是南轅北轍。經(jīng)過(guò)浩瀚文章搜索發(fā)掘下依舊一無(wú)所獲之后,直接導(dǎo)致了我萌生一股寫(xiě)一篇 CSS設(shè)計(jì)模式的沖動(dòng),至此寫(xiě)下這篇文章,其中敘述如有不當(dāng)之處,也懇請(qǐng)各位提出意見(jiàn),分享出您寶貴的經(jīng)驗(yàn)。 在寫(xiě)頁(yè)面之中,width, margin, padding這三個(gè)CSS屬性可以說(shuō)是用到頻率最高的幾個(gè)屬性之一。但根據(jù)我的觀點(diǎn)來(lái)看,許多人,甚至于大多數(shù)前端對(duì)于這三個(gè)屬性的書(shū)寫(xiě)把握上乏善可 陳,以至于兼容和靈活性不得兼顧,導(dǎo)致日后的開(kāi)發(fā)維護(hù)成本直線上升,代碼不斷增長(zhǎng),覆蓋重寫(xiě)樣式,接著再修復(fù)一個(gè)又一個(gè)的Bug。這樣的情況下,使用一種 合理高效的CSS設(shè)計(jì)模式不失為一種明智的選擇,個(gè)人稱(chēng)之為:width,margin,padding三權(quán)分立模式(以下簡(jiǎn)稱(chēng)三權(quán)分立模式)。 什么是三權(quán)分立模式: 說(shuō)明這個(gè)模式之前,必定先要明白什么是盒子模型,你可以參考如下Firebug的盒模型截圖:
注意:在圖上表示margin的顏色為白色(實(shí)質(zhì)是透明)。Margin比較特別,它不會(huì)影響盒子本身的大小,但是它會(huì)影響和盒子有關(guān)的其他內(nèi)容,因此margin也是盒模型的一個(gè)重要的組成部分。 盒子本身的大小是這樣計(jì)算的: Width: width + padding-left + padding-right + border-left + border-right 通過(guò)圖中我們得知,Width(物理總寬度)/Height(物理總高度),是由width/height,padding,border三者之和來(lái)決定的。但簡(jiǎn)單淺顯的盒模型一旦牽涉到CSS中,便會(huì)出現(xiàn)不小的意外。 假設(shè),需要要一個(gè)300px寬,80px高的盒子,里面放一段文字,文字離邊有10px間距。那么一般Html和CSS寫(xiě)法為: HTML代碼:
CSS代碼:
來(lái)分析一下這段CSS代碼,因?yàn)樾枰獫M(mǎn)足300px寬,且文字間隔為10px,所以Width(300px) = width(280px) + padding(10px) X 2。假設(shè)過(guò)了段時(shí)間需要改版,要求為這個(gè)Box添加1px顏色為#ccc的邊框,那么我們?cè)俅握业竭@段CSS,開(kāi)始動(dòng)手修改,加個(gè)boder:1px solid #ccc;: CSS代碼:
之后測(cè)試一下,咦!似乎有點(diǎn)問(wèn)題,哦,因?yàn)榧恿诉吙蛩杂侄嗔?px像素的寬,所以要減去這2px。 CSS代碼:
測(cè)試一下,問(wèn)題解決了。正當(dāng)歡心不已準(zhǔn)備休息時(shí)候,設(shè)計(jì)師跑來(lái)說(shuō),根據(jù)最新要求,希望能再把文字與邊距拉大,上下邊距為10px,左右改為15px。繼續(xù)修改: CSS代碼:
經(jīng)過(guò)“精確”計(jì)算后終于得出了如上的CSS結(jié)果。一次又一次的不斷改版,修改的頁(yè)面數(shù)量越來(lái)越大,其中的代碼越發(fā)復(fù)雜,計(jì)算量也越發(fā)龐大,你只能一 邊為自己的精確到1px像素級(jí)的“專(zhuān)業(yè)”功力而沾沾自喜,而后又不得不疲于奔波與各個(gè)頁(yè)面中的寬高計(jì)算。就這樣一個(gè)又一個(gè)只有你才能明白的代碼出現(xiàn)了! 如何才能擺脫這樣的無(wú)效代碼問(wèn)題呢?這里使用CSS三權(quán)分立模式可謂是最佳解決方案。 CSS三權(quán)分立模式的核心在于完全分離width,margin,padding這三個(gè)CSS屬性,一個(gè)class里只能擁有三個(gè)屬性里的其中一個(gè),而通過(guò)增加一個(gè)額外標(biāo)簽使得能夠通過(guò)多個(gè)class控制元素的外觀,解除三者的耦合。 就如以上問(wèn)題為例,重寫(xiě)300px寬,80px高的盒子,文字離邊有10px間距。使用三權(quán)分立模式下的寫(xiě)法為: Html代碼:
CSS代碼:
這里的寬度、高度、間距的數(shù)值同需求完全一致,無(wú)需計(jì)算。接下來(lái)遇到改版問(wèn)題為Box添加1px顏色為#ccc的邊框,只需這么修改: CSS代碼:
直接為內(nèi)部標(biāo)簽class上添加邊框,單刀直入添加邊框?qū)傩约纯?。最后一關(guān)如需把文字與邊距拉大,上下邊距為10px,左右邊距為15px。 CSS代碼:
注意:上例可以看到padding與border其實(shí)在“寬度占有”的性質(zhì)上是一致的(從某個(gè)角度來(lái)說(shuō)把border設(shè)置為透明再設(shè)置一定寬度就是變相的padding),所以完全可以讓這倆個(gè)屬性寫(xiě)在同一class里,二者性質(zhì)類(lèi)同,無(wú)需再分離這倆個(gè)屬性。 我們可以看出使用三權(quán)分立模式書(shū)寫(xiě)代碼的簡(jiǎn)潔與高效,而且從可讀性及維護(hù)性上有質(zhì)的飛躍。唯一多的就是為內(nèi)部添加一個(gè)額外的標(biāo)簽保證padding/border不會(huì)與width產(chǎn)生干擾,解除二者的耦合關(guān)系,這也是獲得可維護(hù)性需要付出代價(jià)。 在剛才的例子中似乎忽略了另外一個(gè)屬性——Margin。這里的Margin在三權(quán)分立模式中的立場(chǎng)相對(duì)于上面的width與padding耦合強(qiáng) 度下似乎并沒(méi)有那么明顯,但以我的個(gè)人觀點(diǎn)上來(lái)看:Margin的分離是三權(quán)分立模式之中最為重要的一環(huán)。為什么Margin在這里如此重要?因?yàn)檫@里可 以看出一名前端開(kāi)發(fā)人員功力素養(yǎng)——代碼可重用性。 提及代碼可重用性,任何一門(mén)計(jì)算機(jī)語(yǔ)言都有所闡述,而CSS代碼可重用性對(duì)于一名前端來(lái)說(shuō)不亞于對(duì)JS重構(gòu)的重要性。CSS的可重用性會(huì)直接影響HTML代碼的可復(fù)用性。 再回頭看如上代碼,這里的盒子僅僅是一個(gè)頁(yè)面的一小部分而已??v觀整個(gè)網(wǎng)站,不會(huì)也不可能出現(xiàn)只需要一個(gè)模塊的頁(yè)面。每寫(xiě)一個(gè)模塊,將來(lái)就要和各式各樣的頁(yè)面進(jìn)行整合、維護(hù)、開(kāi)發(fā)。 繼續(xù)上面例子,現(xiàn)在我們做好了這個(gè)模塊,開(kāi)始行進(jìn)頁(yè)面的整合。假設(shè)這個(gè)模塊所放的位置同左邊的間隔需為10px,同上方模塊間隔15px,可能會(huì)這么寫(xiě): CSS代碼:
這里的寫(xiě)法原本是沒(méi)有大過(guò)錯(cuò)的,既然提出了Margin分離的重要性,當(dāng)然不會(huì)那么簡(jiǎn)單的糊弄過(guò)去的。記?。耗闼鶎?xiě)的每一個(gè)模塊的代碼將來(lái)都會(huì)有被復(fù)用到另外一個(gè)頁(yè)面(項(xiàng)目)的可能性,甚至于我曾看到過(guò)一個(gè)模塊被幾個(gè)不同的頁(yè)面反復(fù)重用。 說(shuō)到這里,繼續(xù)下去,假設(shè)這個(gè)模塊需要在另外一塊地方使用,而那里設(shè)計(jì)位置要求必須是同上方間隔為0px,離左邊5px。內(nèi)容結(jié)構(gòu)完全一致,遇到這樣的情況,你會(huì)如何解決? 一般遇到這種情況,第一種做法有人會(huì)對(duì)原先代碼視而不見(jiàn),直接重寫(xiě)一份新的HTML和CSS。你別說(shuō),我還真遇到過(guò)。第二種做法或許會(huì)這么修改HTML和CSS: HTML代碼:
CSS代碼:
添加一個(gè)結(jié)合選擇器限定覆蓋原先的margin屬性,這一類(lèi)做法是比較聰明的辦法,如果這個(gè)模塊多次重用則添加多個(gè)結(jié)合選擇器即可,我曾今也常使用類(lèi)似做法來(lái)修復(fù)各類(lèi)的Bug。 或許上面的方法的確可以解決類(lèi)似的問(wèn)題,但作為一名喜歡沒(méi)事瞎琢磨點(diǎn)東西的我來(lái)說(shuō)總覺(jué)得有什么地方不對(duì)。在不斷的思考下最終發(fā)現(xiàn)這個(gè)并非是真正重用,只是一種“修復(fù)”,從某個(gè)角度上來(lái)說(shuō),這不過(guò)是為這個(gè)模塊打一個(gè)“補(bǔ)丁”。一個(gè)又一個(gè)結(jié)合選擇器不就是一個(gè)個(gè)小的補(bǔ)丁嵌入到不同的頁(yè)面中去么,依然會(huì)有那么多多余的代碼會(huì)被寫(xiě)入,這并非是理想中的重用。 理想的重用是不添加任何代碼,僅僅使用原先的代碼就能完全搞定所有的模塊,雖然只是理想狀態(tài),但我們可以不斷的向這個(gè)目標(biāo)靠近。在研究一些CSS庫(kù)后,發(fā)現(xiàn)很多地方同自己的想法不謀而合,其中Margin分離就是其中之一,我們來(lái)看看以下代碼片段: CSS代碼:
以上其實(shí)就是一個(gè)CSS公用文件的一段代碼摘抄,其思想引入這些公用的CSS類(lèi),單獨(dú)定義Margin。通過(guò)簡(jiǎn)寫(xiě)命名,即使用頭字母來(lái)記憶里面的屬性,例如:mt15就是margin-top:15px的意思,下面來(lái)看我們?nèi)绾问褂盟伞?/p> 原先那個(gè)模塊整合到頁(yè)面中需要離上15px,離左10px,使用CSS庫(kù)的做法就是這么寫(xiě)的: HTML代碼:
CSS代碼:
剔除多余的結(jié)合選擇器,選擇可以高度重用的CSS屬性,這里你或許覺(jué)得沒(méi)有多大意義,但如果需要把這個(gè)模塊放入別的頁(yè)面呢,就如上面又要放置在同上方間隔為0,離左邊5px的地方,此效用開(kāi)始發(fā)揮作用了,直接修改HTML代碼,無(wú)需任何的CSS的修改,模塊的高度復(fù)用: HTML代碼:
這樣子你還會(huì)認(rèn)為原先的選擇器做法是正確的么。個(gè)人認(rèn)為:Margin是阻礙模塊重用的最大殺手,因?yàn)槿魏我粋€(gè)組件都或多或少會(huì)添加 Margin這個(gè)屬性來(lái)間隔開(kāi)自身同他人的距離,直接拷貝原先代碼,則先前適用Margin的屬性反而成為了新組件位置的阻礙,及時(shí)分離Margin可以 有效的解除組件同Margin的耦合,達(dá)到重復(fù)使用的效果。 這就是三權(quán)分立模式的全貌,width,margin,padding這三個(gè)屬性完全的分離,大大提高的代碼的可復(fù)用性,可維護(hù)性,解除三者的耦合,為將來(lái)的開(kāi)發(fā)維護(hù)打下堅(jiān)實(shí)的基礎(chǔ),也是CSS設(shè)計(jì)模式的優(yōu)勢(shì)所在。 當(dāng)然設(shè)計(jì)模式也有他的二個(gè)弊端: 復(fù)雜性:獲得可維護(hù)性往往要付出代價(jià),那就是代碼可能會(huì)變得更加復(fù)雜、更難被新手理解。三權(quán)分立模式中的導(dǎo)入公共CSS重用模塊,書(shū)寫(xiě)多個(gè)class合并代替使用單一class都是所需要考慮和規(guī)范的。 性能:多數(shù)的設(shè)計(jì)模式對(duì)代碼的性能會(huì)有所拖累,這種拖累可能微不足道,也可能完全不能接受,這取決于項(xiàng)目的具體要求。這里的三權(quán)分立模式就需要額外添加一個(gè)內(nèi)部標(biāo)簽來(lái)分離padding屬性。 實(shí)現(xiàn)設(shè)計(jì)模式比較容易,而懂得應(yīng)該在什么時(shí)候使用什么模式則較為困難。你應(yīng)該盡量保證所選用的模式就是最恰當(dāng)?shù)哪欠N,并且不要過(guò)度犧牲性能。這對(duì)于 個(gè)人開(kāi)發(fā)甚至于一個(gè)團(tuán)隊(duì)的開(kāi)發(fā)維護(hù)都具有莫大的幫助,個(gè)人認(rèn)為使用三權(quán)分立模式是利遠(yuǎn)大于弊的,希望你也能夠了解他的思想與作用,在團(tuán)隊(duì)開(kāi)發(fā)中使用他,維 護(hù)他,三權(quán)分立模式現(xiàn)實(shí)應(yīng)用可以幫助你和你的團(tuán)隊(duì)開(kāi)發(fā)出更加茁壯的代碼。 寫(xiě)了那么多,只希望你能了解到使用合理的CSS設(shè)計(jì)模式可以幫助我們優(yōu)化代碼,其最終目的是為了CSS開(kāi)發(fā)維護(hù)的高效性和可維護(hù)性,而其魅力也在于此。謝謝! |
|
來(lái)自: 我愛(ài)孟津網(wǎng) > 《css》