CSS設計模式之三權分立模式篇

市面上咱們經常會看到各類各樣的設計模式書籍,Java設計模式、C#設計模式、Ruby設計模式等等。在衆多的語言設計模式中我惟獨找不到關於CSS設計模式的資料,即便在網上找到相似內容,細細一看之下才發覺是南轅北轍。通過浩瀚文章搜索發掘下依舊一無所得以後,直接致使了我萌生一股寫一篇CSS設計模式的衝動,至此寫下這篇文章,其中敘述若有不當之處,也懇請各位提出意見,分享出您寶貴的經驗。css

在寫頁面之中,width, margin, padding這三個CSS屬性能夠說是用到頻率最高的幾個屬性之一。但根據個人觀點來看,許多人,甚至於大多數前端對於這三個屬性的書寫把握上乏善可陳,以致於兼容和靈活性不得兼顧,致使往後的開發維護成本直線上升,代碼不斷增加,覆蓋重寫樣式,接着再修復一個又一個的Bug。這樣的狀況下,使用一種合理高效的CSS設計模式不失爲一種明智的選擇,我的稱之爲:width,margin,padding三權分立模式(如下簡稱三權分立模式)。前端

什麼是三權分立模式:設計模式

說明這個模式以前,一定先要明白什麼是盒子模型,你能夠參考以下Firebug的盒模型截圖:性能

Firebug Box Model Display

 

注意:在圖上表示margin的顏色爲白色(實質是透明)。Margin比較特別,它不會影響盒子自己的大小,可是它會影響和盒子有關的其餘內容,所以margin也是盒模型的一個重要的組成部分。測試

盒子自己的大小是這樣計算的:優化

Width: width + padding-left + padding-right + border-left + border-right
Height: height + padding-top + padding-bottom + border-top + border-bottom網站

經過圖中咱們得知,Width(物理總寬度)/Height(物理總高度),是由width/height,padding,border三者之和來決定的。但簡單淺顯的盒模型一旦牽涉到CSS中,便會出現不小的意外。spa

假設,須要要一個300px寬,80px高的盒子,裏面放一段文字,文字離邊有10px間距。那麼通常Html和CSS寫法爲:設計

HTML代碼:code

1
2
3
< div class = "box" >
   市面上咱們經常會看到各類各樣的設計模式書籍,Java設計模式、C#設計模式、Ruby設計模式等等。
</ div >

CSS代碼:

.box{width:280px; height:60px; padding:10px;}

來分析一下這段CSS代碼,由於須要知足300px寬,且文字間隔爲10px,因此Width(300px) = width(280px) + padding(10px) X 2。假設過了段時間須要改版,要求爲這個Box添加1px顏色爲#ccc的邊框,那麼咱們再次找到這段CSS,開始動手修改,加個boder:1px solid #ccc;:

CSS代碼:

.box{width:280px; height:60px; padding:10px; border:1px solid #ccc;}

以後測試一下,咦!彷佛有點問題,哦,由於加了邊框因此又多了2px像素的寬,因此要減去這2px。

CSS代碼:

.box{width:278px; height:58px; padding:10px; border:1px solid #ccc;}

測試一下,問題解決了。正當歡心不已準備休息時候,設計師跑來講,根據最新要求,但願能再把文字與邊距拉大,上下邊距爲10px,左右改成15px。繼續修改:

CSS代碼:

.box{width:268px; height:58px; padding:10px 15px; border:1px solid #ccc;}

通過「精確」計算後終於得出瞭如上的CSS結果。一次又一次的不斷改版,修改的頁面數量愈來愈大,其中的代碼愈加複雜,計算量也愈加龐大,你只能一邊爲本身的精確到1px像素級的「專業」功力而沾沾自喜,然後又不得不疲於奔波與各個頁面中的寬高計算。就這樣一個又一個只有你才能明白的代碼出現了!

如何才能擺脫這樣的無效代碼問題呢?這裏使用CSS三權分立模式可謂是最佳解決方案。

CSS三權分立模式的核心在於徹底分離width,margin,padding這三個CSS屬性,一個class裏只能擁有三個屬性裏的其中一個,而經過增長一個額外標籤使得可以經過多個class控制元素的外觀,解除三者的耦合。

就如以上問題爲例,重寫300px寬,80px高的盒子,文字離邊有10px間距。使用三權分立模式下的寫法爲:

Html代碼:

1
2
3
4
5
< div class = "box" >
   < div class = "roundBox" >
     市面上咱們經常會看到各類各樣的設計模式書籍,Java設計模式、C#設計模式、Ruby設計模式等等。
   </ div >
</ div >

CSS代碼:

.box{width:300px; height:80px;}
.box .roundBox{padding:10px;}

這裏的寬度、高度、間距的數值同需求徹底一致,無需計算。接下來遇到改版問題爲Box添加1px顏色爲#ccc的邊框,只需這麼修改:

CSS代碼:

.box{width:300px; height:80px;}
.box .roundBox{padding:10px; border:1px solid #ccc;}

直接爲內部標籤class上添加邊框,單刀直入添加邊框屬性便可。最後一關如需把文字與邊距拉大,上下邊距爲10px,左右邊距爲15px。

CSS代碼:

.box{width:300px; height:80px;}
.box .roundBox{padding:10px 15px; border:1px solid #ccc;}

注意:上例能夠看到padding與border其實在「寬度佔有」的性質上是一致的(從某個角度來講把border設置爲透明再設置必定寬度就是變相的padding),因此徹底可讓這倆個屬性寫在同一class裏,兩者性質類同,無需再分離這倆個屬性。

咱們能夠看出使用三權分立模式書寫代碼的簡潔與高效,並且從可讀性及維護性上有質的飛躍。惟一多的就是爲內部添加一個額外的標籤保證padding/border不會與width產生干擾,解除兩者的耦合關係,這也是得到可維護性須要付出代價。

在剛纔的例子中彷佛忽略了另一個屬性——Margin。這裏的Margin在三權分立模式中的立場相對於上面的width與padding耦合強度下彷佛並無那麼明顯,但以個人我的觀點上來看:Margin的分離是三權分立模式之中最爲重要的一環。爲何Margin在這裏如此重要?由於這裏能夠看出一名前端開發人員功力素養——代碼可重用性。

說起代碼可重用性,任何一門計算機語言都有所闡述,而CSS代碼可重用性對於一名前端來講不亞於對JS重構的重要性。CSS的可重用性會直接影響HTML代碼的可複用性。

再回頭看如上代碼,這裏的盒子僅僅是一個頁面的一小部分而已。縱觀整個網站,不會也不可能出現只須要一個模塊的頁面。每寫一個模塊,未來就要和各式各樣的頁面進行整合、維護、開發。

繼續上面例子,如今咱們作好了這個模塊,開始行進頁面的整合。假設這個模塊所放的位置同左邊的間隔需爲10px,同上方模塊間隔15px,可能會這麼寫:

CSS代碼:

.box{width:300px; height:80px; margin:15px 0 0 10px;}
.box .roundBox{padding:10px 15px; border:1px solid #ccc;}

這裏的寫法本來是沒有大過錯的,既然提出了Margin分離的重要性,固然不會那麼簡單的糊弄過去的。記住:你所寫的每個模塊的代碼未來都會有被複用到另一個頁面(項目)的可能性,甚至於我曾看到過一個模塊被幾個不一樣的頁面反覆重用。

說到這裏,繼續下去,假設這個模塊須要在另一塊地方使用,而那裏設計位置要求必須是同上方間隔爲0px,離左邊5px。內容結構徹底一致,遇到這樣的狀況,你會如何解決?

通常遇到這種狀況,第一種作法有人會對原先代碼視而不見,直接重寫一份新的HTML和CSS。你別說,我還真遇到過。第二種作法或許會這麼修改HTML和CSS:

HTML代碼:

1
2
3
4
5
< div class = "box anotherPlace" >
   < div class = "roundBox" >
     市面上咱們經常會看到各類各樣的設計模式書籍,Java設計模式、C#設計模式、Ruby設計模式等等。
   </ div >
</ div >

CSS代碼:

.box{width:300px; height:80px; margin:15px 0 0 10px;}
.box.anotherPlace{margin:0 0 0 5px;}
.box .roundBox{padding:10px 15px; border:1px solid #ccc;}

添加一個結合選擇器限定覆蓋原先的margin屬性,這一類作法是比較聰明的辦法,若是這個模塊屢次重用則添加多個結合選擇器便可,我曾今也常使用相似作法來修復各種的Bug。

或許上面的方法的確能夠解決相似的問題,但做爲一名喜歡沒事瞎琢磨點東西的我來講總以爲有什麼地方不對。在不斷的思考下最終發現這個並不是是真正重用,只是一種「修復」,從某個角度上來講,這不過是爲這個模塊打一個「補丁」。一個又一個結合選擇器不就是一個個小的補丁嵌入到不一樣的頁面中去麼,依然會有那麼多多餘的代碼會被寫入,這並不是是理想中的重用。

理想的重用是不添加任何代碼,僅僅使用原先的代碼就能徹底搞定全部的模塊,雖然只是理想狀態,但咱們能夠不斷的向這個目標靠近。在研究一些CSS庫後,發現不少地方同本身的想法不謀而合,其中Margin分離就是其中之一,咱們來看看如下代碼片斷:

CSS代碼:

.m10{margin:10px}
.m15{margin:15px}
.m30{margin:30px}
.mt5{margin-top:5px}
.mt10{margin-top:10px}
.mt15{margin-top:15px}
.mt20{margin-top:20px}
.mt30{margin-top:30px}
.mt50{margin-top:50px}
.mt100{margin-top:100px}
.mb10{margin-bottom:10px}
.mb15{margin-bottom:15px}
.mb20{margin-bottom:20px}
.mb30{margin-bottom:30px}
.mb50{margin-bottom:50px}
.mb100{margin-bottom:100px}
.ml5{margin-left:5px}
.ml10{margin-left:10px}
.ml15{margin-left:15px}
.ml20{margin-left:20px}
.ml30{margin-left:30px}
.ml50{margin-left:50px}
.ml100{margin-left:100px}
.mr5{margin-right:5px}
.mr10{margin-right:10px}
.mr15{margin-right:15px}
.mr20{margin-right:20px}
.mr30{margin-right:30px}
.mr50{margin-right:50px}
.mr100{margin-right:100px}

以上其實就是一個CSS公用文件的一段代碼摘抄,其思想引入這些公用的CSS類,單獨定義Margin。經過簡寫命名,即便用頭字母來記憶裏面的屬性,例如:mt15就是margin-top:15px的意思,下面來看咱們如何使用它吧。

原先那個模塊整合到頁面中須要離上15px,離左10px,使用CSS庫的作法就是這麼寫的:

HTML代碼:

1
2
3
4
5
< div class = "box mt15 ml10" >
   < div class = "roundBox" >
     市面上咱們經常會看到各類各樣的設計模式書籍,Java設計模式、C#設計模式、Ruby設計模式等等。
   </ div >
</ div >

CSS代碼:

.box{width:300px; height:80px;}
.box .roundBox{padding:10px 15px; border:1px solid #ccc;}

剔除多餘的結合選擇器,選擇能夠高度重用的CSS屬性,這裏你或許以爲沒有多大意義,但若是須要把這個模塊放入別的頁面呢,就如上面又要放置在同上方間隔爲0,離左邊5px的地方,此效用開始發揮做用了,直接修改HTML代碼,無需任何的CSS的修改,模塊的高度複用:

HTML代碼:

1
2
3
4
5
< div class = "box ml5" >
   < div class = "roundBox" >
     市面上咱們經常會看到各類各樣的設計模式書籍,Java設計模式、C#設計模式、Ruby設計模式等等。
   </ div >
</ div >

這樣子你還會認爲原先的選擇器作法是正確的麼。我的認爲:Margin是阻礙模塊重用的最大殺手,由於任何一個組件都或多或少會添加Margin這個屬性來間隔開自身同他人的距離,直接拷貝原先代碼,則先前適用Margin的屬性反而成爲了新組件位置的阻礙,及時分離Margin能夠有效的解除組件同Margin的耦合,達到重複使用的效果。

這就是三權分立模式的全貌,width,margin,padding這三個屬性徹底的分離,大大提升的代碼的可複用性,可維護性,解除三者的耦合,爲未來的開發維護打下堅實的基礎,也是CSS設計模式的優點所在。

固然設計模式也有他的二個弊端:

複雜性:得到可維護性每每要付出代價,那就是代碼可能會變得更加複雜、更難被新手理解。三權分立模式中的導入公共CSS重用模塊,書寫多個class合併代替使用單一class都是所須要考慮和規範的。

性能:多數的設計模式對代碼的性能會有所拖累,這種拖累可能微不足道,也可能徹底不能接受,這取決於項目的具體要求。這裏的三權分立模式就須要額外添加一個內部標籤來分離padding屬性。

實現設計模式比較容易,而懂得應該在何時使用什麼模式則較爲困難。你應該儘可能保證所選用的模式就是最恰當的那種,而且不要過分犧牲性能。這對於我的開發甚至於一個團隊的開發維護都具備莫大的幫助,我的認爲使用三權分立模式是利遠大於弊的,但願你也可以瞭解他的思想與做用,在團隊開發中使用他,維護他,三權分立模式現實應用能夠幫助你和你的團隊開發出更加茁壯的代碼。

寫了那麼多,只但願你能瞭解到使用合理的CSS設計模式能夠幫助咱們優化代碼,其最終目的是爲了CSS開發維護的高效性和可維護性,而其魅力也在於此。謝謝!

相關文章
相關標籤/搜索