1. 程式人生 > >從div盒子模型談如何寫可維護的css程式碼

從div盒子模型談如何寫可維護的css程式碼

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

什麼是三權分立模式:

說明這個模式之前,必定先要明白什麼是盒子模型,你可以參考如下Firebug的盒模型截圖:

注意:在圖上表示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中,便會出現不小的意外。

假設,需要要一個300px寬,80px高的盒子,裡面放一段文字,文字離邊有10px間距。那麼一般Html和CSS寫法為:

HTML程式碼:

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

CSS程式碼:

.程式碼 
  1. .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;:

可以500%提高開發效率的前端UI框架!

CSS程式碼:

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

之後測試一下,咦!似乎有點問題,哦,因為加了邊框所以又多了2px畫素的寬,所以要減去這2px。

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

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

.程式碼 
  1. .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. <div class="box">  
  2.   <div class="roundBox">  
  3.     市面上我們常常會看到各種各樣的設計模式書籍,Java設計模式、C#設計模式、Ruby設計模式等等。  
  4.   </div>  
  5. </div>  

CSS程式碼:

.程式碼 
  1. .box{width:300px; height:80px;}  
  2. .box .roundBox{padding:10px;}  

這裡的寬度、高度、間距的數值同需求完全一致,無需計算。接下來遇到改版問題為Box新增1px顏色為#ccc的邊框,只需這麼修改: 可以500%提高開發效率的前端UI框架!

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

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

.程式碼 
  1. .box{width:300px; height:80px;}  
  2. .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,可能會這麼寫: 可以500%提高開發效率的前端UI框架!

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

這裡的寫法原本是沒有大過錯的,既然提出了Margin分離的重要性,當然不會那麼簡單的糊弄過去的。記住:你所寫的每一個模組的程式碼將來都會有被複用到另外一個頁面(專案)的可能性,甚至於我曾看到過一個模組被幾個不同的頁面反覆重用。

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

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

HTML程式碼:

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

CSS程式碼:

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

新增一個結合選擇器限定覆蓋原先的margin屬性,這一類做法是比較聰明的辦法,如果這個模組多次重用則新增多個結合選擇器即可,我曾今也常使用類似做法來修復各類的Bug。可以500%提高開發效率的前端UI框架!

或許上面的方法的確可以解決類似的問題,但作為一名喜歡沒事瞎琢磨點東西的我來說總覺得有什麼地方不對。在不斷的思考下最終發現這個並非是真正重用,只是一種“修復”,從某個角度上來說,這不過是為這個模組打一個“補丁”。一個又一個結合選擇器不就是一個個小的補丁嵌入到不同的頁面中去麼,依然會有那麼多多餘的程式碼會被寫入,這並非是理想中的重用。

理想的重用是不新增任何程式碼,僅僅使用原先的程式碼就能完全搞定所有的模組,雖然只是理想狀態,但我們可以不斷的向這個目標靠近。在研究一些CSS庫後,發現很多地方同自己的想法不謀而合,其中Margin分離就是其中之一,我們來看看以下程式碼片段:

CSS程式碼:

.程式碼 
  1. .m10{margin:10px}  
  2. .m15{margin:15px}  
  3. .m30{margin:30px}  
  4. .mt5{margin-top:5px}  
  5. .mt10{margin-top:10px}  
  6. .mt15{margin-top:15px}  
  7. .mt20{margin-top:20px}  
  8. .mt30{margin-top:30px}  
  9. .mt50{margin-top:50px}  
  10. .mt100{margin-top:100px}  
  11. .mb10{margin-bottom:10px}  
  12. .mb15{margin-bottom:15px}  
  13. .mb20{margin-bottom:20px}  
  14. .mb30{margin-bottom:30px}  
  15. .mb50{margin-bottom:50px}  
  16. .mb100{margin-bottom:100px}  
  17. .ml5{margin-left:5px}  
  18. .ml10{margin-left:10px}  
  19. .ml15{margin-left:15px}  
  20. .ml20{margin-left:20px}  
  21. .ml30{margin-left:30px}  
  22. .ml50{margin-left:50px}  
  23. .ml100{margin-left:100px}  
  24. .mr5{margin-right:5px}  
  25. .mr10{margin-right:10px}  
  26. .mr15{margin-right:15px}  
  27. .mr20{margin-right:20px}  
  28. .mr30{margin-right:30px}  
  29. .mr50{margin-right:50px}  
  30. .mr100{margin-right:100px}  

以上其實就是一個CSS公用檔案的一段程式碼摘抄,其思想引入這些公用的CSS類,單獨定義Margin。通過簡寫命名,即使用頭字母來記憶裡面的屬性,例如:mt15就是margin-top:15px的意思,下面來看我們如何使用它吧。可以500%提高開發效率的前端UI框架!

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

HTML程式碼:

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

CSS程式碼:

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

剔除多餘的結合選擇器,選擇可以高度重用的CSS屬性,這裡你或許覺得沒有多大意義,但如果需要把這個模組放入別的頁面呢,就如上面又要放置在同上方間隔為0,離左邊5px的地方,此效用開始發揮作用了,直接修改HTML程式碼,無需任何的CSS的修改,模組的高度複用:

HTML程式碼:

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

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

這就是三權分立模式的全貌,width,margin,padding這三個屬性完全的分離,大大提高的程式碼的可複用性,可維護性,解除三者的耦合,為將來的開發維護打下堅實的基礎,也是CSS設計模式的優勢所在。

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

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

效能:多數的設計模式對程式碼的效能會有所拖累,這種拖累可能微不足道,也可能完全不能接受,這取決於專案的具體要求。這裡的三權分立模式就需要額外新增一個內部標籤來分離padding屬性。可以500%提高開發效率的前端UI框架!

實現設計模式比較容易,而懂得應該在什麼時候使用什麼模式則較為困難。你應該儘量保證所選用的模式就是最恰當的那種,並且不要過度犧牲效能。這對於個人開發甚至於一個團隊的開發維護都具有莫大的幫助,個人認為使用三權分立模式是利遠大於弊的,希望你也能夠了解他的思想與作用,在團隊開發中使用他,維護他,三權分立模式現實應用可以幫助你和你的團隊開發出更加茁壯的程式碼。

寫了那麼多,只希望你能瞭解到使用合理的CSS設計模式可以幫助我們優化程式碼,其最終目的是為了CSS開發維護的高效性和可維護性,而其魅力也在於此。