2010年9月15日 星期三

CSS觀念好文:CSS 團隊開發的最佳實踐

我一向很少轉貼文章,但這一篇國外作者Emily P. Lewis寫的CSS文章,講的相當精鍊實務,對於學習與釐清CSS觀念上真的是相當不錯,尤其在面對大型網站管理上,可算是深得我心,因此仍是貼來跟大家分享,原文出自於台灣微軟的MSDN網站 http://msdn.microsoft.com/zh-tw/scriptjunkie/ff679957.aspx


多少次你撿起一個別人啟動的專案,發現原始碼是一團混亂?或者是你和幾個團隊成員合作,每個人都有自己一套寫法?又或者你重新檢視幾年前自己建立的專案,而你記不起來那時究竟在想什麼?
這些都常發生在我身上。事實上,最近我花了近 300 個小時,修改一個廠商令人掩面的 CSS。這 300 個小時不僅讓我感到相當挫折,對我團隊中的其他人也一樣。它偷走了珍貴的時間和資源,這些本來可以更好地運用在新的開發工作上。
假如那個廠商只要在他的 CSS 中遵循簡單的原則,我的團隊就能節省下金錢和時間,更別說我自己的理智會保持在更好的狀態。在這篇文章中,你會學到撰寫 CSS 的最佳實踐,這可以幫助你避免不一致和冗贅;實際上,可以為簡化團隊開發設下標準。
無論你是和內部的團隊,或是面對廠商、外包商,甚至你自己就是一人團隊,這些 CSS 實踐會幫助你建立基礎規則,讓你成為一個好的 CSS 團隊的一員,進而節省時間和挫折感。
你需要做的,只要回想起小時候聽過的黃金法則,並牢牢地記住:善待你的 CSS,如同你希望別人怎麼對待它。




讓它組織起來!
好的組織是撰寫良好 CSS 的基礎。它幫助我-還有日後需要修改這個語法的人-可以更了解和掃讀 CSS,並快速跳到特定的樣式。
在我正式開始寫樣式之前,首先我定義 CSS 文件的組識,它是依據網頁不同內容的「段落」來定義。而且這些段落在不同的網站經常是一樣的:

  • Header
  • Navigation
  • Main content
  • Sidebar
  • Footer
所以,在我的 CSS 檔案中,我加上一些註解,標示每個即將加上樣式的段落:


  1. /*---GLOBAL---*/
  2. /*---HEADER---*/
  3. /*---NAV---*/
  4. /*---CONTENT---*/
  5. /*---SIDEBAR---*/
  6. /*---FOOTER---*/
注意一開始的註解我加上了 GLOBAL 這個註解,這個段落不符合網站其他部分的內容,它用來處理我所謂的「全域」樣式。這些都是通用的樣式,而不是專指某部分的內容,像是外觀/結構、排版元素-標題、段落、清單和連結等- 以及 <form> 和 <table> 等。
藉由保持全域狀態,通用樣式放置在 CSS 檔案頂端,它可以讓我運用串接的優勢。所有依循這些樣式宣告的 CSS,將會繼承這些屬性,因此在需要時,我可以更容易覆寫這些屬性。




更多的 CSS,更多的組識性
我在非常大型的網站工作,而它相當倚賴 CSS。在處理大量行數的樣式時,我喜歡在每個段落加上第二層註解。以 GLOBAL 為例,我會寫下將要維護的樣式類型:


  1. /*---GLOBAL---*/
  2.     /*--Structure--*/
  3.     /*--Typographic--*/
  4.     /*--Forms--*/
  5.     /*--Tables--*/
  6. /*---HEADER---*/
  7. /*---NAV---*/
  8.     /*--Primary--*/      
  9.     /*--Secondary--*/ 
  10.     /*---CONTENT---*/ 
  11. /*---SIDEBAR---*/ 
  12. /*---FOOTER---*/
你會注意到我也在 NAV 加上了第二層註解,指出還有主要和次要的導覽列。
這也許對你的目的而言有點超過了。事實上,對於較小的網站、需要的 CSS 較少,通常我就不會用第二層註解了。不過在大型 CSS 檔案上,這個額外的細節對我的團隊帶來許多幫助。




自由的格式
這些為了組識結構的註解格式,可以由你自己決定。上面的範例只是我和我的團隊喜歡的方法。有些人喜歡他們的註解採兩行的方式:


  1. /*   HEADER     
  2. ------------------------------*/
有些人使用特殊的字元,像是等號,用作標示,以方便在文字編輯器協助搜尋


  1. /*   =Header     
  2. ------------------------------*/
有些人不使用第二層註解。有些人使用完全不同的組識結構,不依賴頁面內容,而是透過元素型態:headers、images、lists 等。關鍵在於以你自己喜愛的格式定義,然後持續地使用它
想要依照內容元素來組織?沒問題。如果你想將註解小寫,儘管去做。不想內縮第二層註解,那就別做。不想使用連字符號而想用句點?那就瘋狂一下吧。去做對你和你的團隊覺得合理的方法。




溝通用的註解
我們已經看了組識結構所用的註解,不過你也應該使用註解來和其他團隊成員溝通,甚至是跟未來的自己溝通。



何事、何人、何時
當以團隊的一份子在工作時,給與 CSS 檔案註解是誰撰寫,什麼時候最後更新,這些資訊對成員間溝通特別有用。在我的團隊上,我們在 CSS 檔案的上方加入了「摘要」註解,它提供了這些細節:


  1. /*----TITLE: Main screen styles | AUTHOR: EPL | UPDATED: 03/23/10 by EPL----*/
這個資訊在使用多個樣式時相當有用,例如一個用在螢幕上,一個用在列印上,另一個用在行動裝置上,甚至用於 IE hack 上。作者資訊可以讓所有團隊的成員知道,原始的 CSS 有問題時該去問誰,而更新資訊讓團隊知道最後在什麼時候,由誰更新了這個檔案。
至於你的摘要註解,只需保含對你的團隊有用的資訊。假如你不需要作者資訊,就略過它。假如你需要版權宣告,就加上它。我曾見過許多摘要註解,裡面加上了住址和聯絡方式:



  1. /*---- IE6 screen styles (ie6.css)  Company ABC 1234 Avenue of the Americas New York, NY 10020 http://companyabc.com  Updated: 03/23/10 by EPL ----*/



色彩鍵值
我遇過最有用的 CSS 註解是加上色彩鍵值,它註解了網站使用的色盤:


  1. /*---COLORS: Green #b3d88c | Blue #0075b2 | Light Gray #eee | Dark Gray #9b9e9e | Orange #f26522 | Teal #00a99d | Yellow #fbc112---*/
色彩值在開發階段特別有用,它可以節省你的時間去找色彩範例或從一些樣式指引中東翻西找。需要知道藍色連結的 16 進位值?捲動到定義鍵值的地方,然後剪下、貼上。
在我的團隊中,我們在 CSS 文件頂端維護了一個色彩鍵值,就在註解摘要的後面、樣式宣告之前,而和組織結構的註解在一起。不過它也取決於你想做到多複雜。
當然格式也由你決定。你可以讓所有的定義通通合在一行,如同上面的例子,或者將它們分開成多行:



  1. /*---COLORS     
  2. Green #b3d88c     
  3. Blue #0075b2     
  4. Light Gray #eee     
  5. Dark Gray #9b9e9e     
  6. Orange #f26522     
  7. Teal #00a99d     
  8. Yellow #fbc112
  9. ---*/
再一次,目標是找出對符合團隊需求最合宜的格式,然後持續地使用那個格式。



開發與除錯
有時當開發工作進行到一半時,我必須將手邊的 CSS 交給其他的成員。有時候我會去撞牆,只為了想出為什麼IE破壞了我的 CSS,而我又必須走開。這些情況發生時,溝通是必要的手段。
寫下一個註解給自己或你的成員,指出一個樣式為什麼這樣或不這樣寫,能省下他們的時間,避免他們頭痛:



  1. /*--//--連結狀態的樣式暫緩,等待設計師的新樣式,請不要編輯 | EPL 03/23/10--\\--*/
  2. a, a:link, a:visited {   
  3.     color:#0075b2;    
  4.     text-decoration:none;
  5.  
  6. a:hover, a:focus, a:active {   
  7.     color:#b3d88c;
  8. }
通常我會使用有別於其他的不同註解方式,讓它們可以更為突顯。而且我會盡量寫清楚所需的細節。同樣的,用最適合你的方式。
不過記住,當你完成了開發/除錯之後,把這類型的註解移除是個好主意。假如這些不再和工作相關,它們也沒有理由留在 CSS 中。留著只是徒增檔案大小。





重設
CSS 重設已經蔚為流行。他們是加在 CSS 檔案上方的樣式風格,可以將 HTML 元素設定為基礎值,以避開瀏覽器之間外觀上的不一致 - margin、padding、line-height 等:


  1. /*---RESET---*/
  2. html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {   
  3.     margin: 0;   
  4.     padding: 0;   
  5.     border: 0;   
  6.     outline: 0;   
  7.     font-weight: inherit;   
  8.     font-style: inherit;   
  9.     font-size: 100%;   
  10.     font-family: inherit;   
  11.     vertical-align: baseline;
  12. }
上面的例子是摘自 Eric Meyer 的 Reset Reloaded,而我常使用它。不過傾向於編輯他的重設檔,沒使用到的元素就不寫進去,我建議你也這樣做。例如,我的團隊建立的網站,幾乎從未使用過 <kbd>、 <iframe> 或 <applet> 元素,或是其他一些上面包含的少數元素。
所以我移掉了那些元素,它雖然只會影響到微不足道的頁面下載時間或頻寬,不過我覺得這對於一些從未用過這些元素的團隊成員而言,可以避免一些困擾。
我也會去編輯一些重設風格,如果我希望覆寫瀏覽器預設的樣式,例如非循序清單的樣式。這種情況我會確保他們沒有被包含在重設清單中。
但我必須聲明,CSS 重設並不適合每一個人。有
許多理由不該使用他們。我會說由你自己決定,假如你決定使用,讓你的重設樣式定義簡潔而且盡量適用於你的網站。



語義命名規範
和其他人一起開發 CSS 時,最令人感到挫折的事,莫過於為 class 或 id 使用毫無意義的名稱。想像一下下面的例子:


  1. .f23 {   
  2.     background: #fff;   
  3.     border: 1px solid #ff0;   
  4.     font-weight: bold;   
  5.     padding: 10px;
  6. }
我對 .f23 是什麼毫無頭緒。更糟的是,如果沒有組織過的註解,我不知道 .f23 指的內容究竟是什麼。它是標題嗎?主要的內容嗎?還是導覽列?
在這種情況下,尤其是大型網站,它可能需要浪費大量時間,荒謬地去找出這個 class 的值究竟對應到哪個標籤。假如作者改用語義命名規範—那些有意義、基於內容來做樣式的—我有一個情境可以說明這樣的 CSS:


  1. .alert {   
  2.     background: #fff;   
  3.     border: 1px solid #ff0;   
  4.     font-weight: bold;   
  5.     padding: 10px;
  6. }
如你所見,.alert 提供了更多的情境給 CSS,勝過於任意隨機的英數字組合。
不過不只是情境,語義命名規範對於節省時間也有幫助。試想一家公司經常改變品牌。假如你開發 CSS 使用外觀更勝於語義的 class 和 id 值,你會需要更多的 CSS-甚至更多的標籤-來維護。
例如,如果你指定 class="blueBox" 給一個網站的「跳出方塊」(call-out box),它使用了公司的藍色色盤。之後公司為了重打品牌,換成紅色色盤。這時 blueBox 變得毫無意義。所以,這時不止要更新 CSS 樣式中顏色的 16 進位值,你也必須修改標籤中的所有參照。
假如你改成 class="callOut" 來代替(或其他相同意義的詞),你需要做的事就變少很多。




瘋狂 Class
撰寫 CSS 時,我同意「少就是多」的想法。雖然你可以在每個元素上加上 class,不代表你應該這樣做。
在我修改廠商品質糟糕的 CSS 的那 300 個小時裡,我發現許多不需要存在的 class。舉例來說,每一個 <label> 元素被指派「class="label"」,而每一個 <form> 元素上,也都有「class="form"」。然而我們的設計以及標籤,針對 <form> 元素其實只有一種樣式,<label> 的情況也一樣。



  1. form.form {   
  2.     float: right;   
  3.     margin: 0;   
  4.     padding: 5px;
  5. }
  6.  
  7. label.label {   
  8.     clear: both;   
  9.     float: left;   
  10.     text-align: right;   
  11.     width: 145px;
  12. }
這樣的 CSS 造成的結果雖然不恐怖(只是冗贅,但不恐怖),但卻造成困惑。身為繼承 CSS 的設計師,看到 .from 的 class 時,我就會假設一定有其他有別於 <form> 樣式的 class 值。而尋找這個不存在的樣式,只是虛耗我的時間。



大量 Class != 明確性
上面只是一個簡單的例子。一個我遇過更為詳細的例子,似乎是種渴求明確性的結果所造成:


  1. <div id="feature" class="tabs">   
  2. <ul class="tabs">      
  3. <li class="tabs"><a href="#newServices">New Services</a></li>      
  4.   <li class="tabs"><a href="#newProducts">New Products</a></li>   
  5. </ul>
  6. </div>
注意「class="tabs"」是如何被套用在上的每一個元素上?而下面的 CSS 是用來鎖定清單元素的CSS:


  1. div.tabs ul.tabs li.tabs {   
  2.     float: left;   
  3.     font-weight: bold;   
  4.     padding: 3px;
  5. }
一個鎖定 <li> 更簡潔、輕量的方案如下:


  1. #feature li {   
  2.     float: left;   
  3.     font-weight: bold;   
  4.     padding: 3px;
  5. }
假如你的樣式不需要一個 class 值來鎖定元素,那就別用它。它們會增加你的標籤和 CSS 的體積,而且也大量降低了掃讀 CSS 的速度。
你也應該注意我在最後一個例子中,使用 #featurerather 而不是 div#feature 的 id 作為選取子。只有在有明確指定的必要時,才在選取子上加上 div。如果不這樣做,只是增加 CSS 無謂的內容,而造成你和你的成員必須看更多。此外,盡量使用最少量的明確宣告,它可以在後來需要覆寫樣式時發揮作用。




多重 class
經過一連串的介紹,你也許會有一個我不喜歡用太多 class 的印象。的確我不鼓勵不必要、冗贅的用法,不過在透過指定多重 class,讓 CSS 保持精簡以維持共通性這件事上,我可是個超級粉絲,只是可能需要一點不同的作法:


  1. .announcement {   
  2.     background: #eee;   
  3.     border: 1px solid #007b52;
  4.     color: #007b52;   
  5.     font-weight: bold;   
  6.     padding: 10px;
  7.  
  8. .newsAnnouncement {   
  9.     background: #eee;   
  10.     border: 1px solid #007b52;
  11.     color: #007b52;   
  12.     float: right;   
  13.     font-weight: bold;   
  14.     padding: 10px;
  15. }
上面兩個宣告是類似的,除了 .newsAnnouncement 會往右飄移。與其重複所有共同的樣式資訊,我會改用下面的方式:


  1. .announcement {   
  2.     background: #eee;   
  3.     border: 1px solid #007b52;
  4.     color: #007b52;   
  5.     font-weight: bold;   
  6.     padding: 10px;
  7.  
  8. .floatR {   
  9.     float:right;
  10. }
然後在我的標籤上,替「news announcements」同時指派兩個 class:


  1. <div class="announcement floatR">
等一下,我自己不是說過採用語義命名規範而不是外觀命名嗎?沒錯。不過每一個規則總有例外的時候。
是的,.floatR 是描述外觀的。不過它應用在這種情況時相當自然,而且也適用於其他需要多重類別的情況,所以這個方法也常被我的團隊使用。




群組選取子
在 300 小時煎熬奮鬥史中,我遇到的另一個問題是,在多個樣式表中使用相同的樣式宣告。在宣告間唯一不同之處,就是它們分別套用在不同的選取子:


  1. #productFeature {   
  2.     background: #fff;   
  3.     border: 1px solid #00752b;   
  4.     float: left;   
  5.     padding: 10px;
  6. #contactFeature {   
  7.     background: #fff;   
  8.     border: 1px solid #00752b;   
  9.     float: left;   
  10.     padding: 10px;
  11. }
  12.  
  13. #serviceFeature {   
  14.     background: #fff;   
  15.     border: 1px solid #00752b;   
  16.     float: left;   
  17.     padding: 10px;
  18. }
這不僅讓已嫌龐大的 CSS 文件更為臃腫,更讓維護工作陷入一場惡夢。解決方法應該是結合這些選取子到一個相同的樣式宣告:


  1. #productFeature, #contactFeature, #serviceFeature {   
  2.     background: #fff;   
  3.     border: 1px solid #00752b;   
  4.     float: left;   
  5.     padding: 10px;
  6. }
現在,樣子如果需要更新,只要改動一個地方即可,而不是到三處地方修改。


單行或多行?
這篇文章所有 CSS 的範例都寫成多行格式,每一對「屬性-值」的配對自成一行。這種寫法不僅在 CSS 檔案中廣泛使用,在關於 CSS 的書和文章中也是。多數人覺得這樣的可讀性比較好,這是我在這篇文章中也這樣用的原因。
然而,在我和我的團隊工作時-尤其是大型的 CSS 檔,我會使用單行的方式:



  1. .alert {background: #fff; border: 1px solid #ff0; font-weight: bold; padding: 10px;}
就我個人而言,我覺得這樣的可讀性更好。在處理大量行數的 CSS 時,多行格式就變得有點累贅,不易掃讀。把東西放在一行似乎比較容易做到。
對於你和你的團隊來說,專注在一致性。挑一個對你的團隊而言最舒服的做法,然後反覆持續地用它。




要不要依字母排序?
有些人建議在樣式宣告內,利用字母順序來排序樣式屬性,這樣可以更快、更容易找到屬性。這在過去我沒有特別的感覺,但在處理廠商混亂的 CSS 檔案後,我可以欣賞這種可以讓樣式宣告變得更有組織的好主意。
不過,我發現有比字母排序更為有效的方法,就是依照情境來編排屬性。舉例來說,我喜歡將所有區塊(box)屬性放在一起。或者,像是當我使用絕對定位(absolute postion)時,會將相關的屬性群組起來:



  1. #logo {   
  2.     border: 1px solid #000;   
  3.     margin: 0;   
  4.     padding: 0;   
  5.     position: absolute;   
  6.     top: 5px;   
  7.     right: 3px;
  8. }
再一次,這沒有對錯可言,只是決定一些屬性的順序,然後一致性地應用。



讓縮寫成為你的朋友
使用 CSS 縮寫是長久以來被認為可以保持 CSS 輕量、簡潔的方法。而且它對團隊開發也有巨大的幫助,它不但增加了可讀性,而且設定了讓人人可依循的標準語法。這減少了團隊成員去思考有關撰寫 CSS 的時間。 




零值
如果你指定一個屬性值為 0,那單位值如 pixel(或 em、百分比…)是不必要的:


  1. margin: 2px 3px 0px 4p
改為


  1. margin: 2px 3px 0 4px




16 進位色彩值
16 進行色彩值由三對數字組成,而它可以縮減成對的其中一個數字:


  1. color: #ff0000
變成


  1. color: #f00




區塊屬性
像是 margin 這樣的區塊屬性,padding 和 border 的值可以作結合,如果四個邊的值有相同之處的話:


  1. padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px
變成


  1. padding: 5px
另外使用區塊屬性時,如果上、下或是左、右的值一樣,你只需要宣告成兩組:


  1. padding: 5px 10px 5px 10px
變成


  1. padding: 5px 10px





Font 屬性
Font 屬性也可以作結合:


  1. font-style:italic; font-weight:bold; font-size: 90%; font-family: Arial, Helvetica, sans-serif;
變成


  1. font: italic bold 90% Arial, Helvetica sans-serif







Background 屬性
Background 屬性也是,在合併屬性值上可以做很多:


  1. background-color:#fff; background-image: url(logo.png); background-repeat: no-repeat; background-position: 0 10%;
變成


  1. background: #f00 url(logo.png) no-repeat 0 10%
注意:最後兩個縮寫範例,font 和 background 屬性,屬性宣告的順序是有意義的。以參考 W3C 規則作確認。以參考 W3C 規則作確認。可以參考 W3C 規則作確認。





有效性、有效性、有效性
有些人的經驗法則認為驗證 CSS 的有效性是好作法,而我認為它應該是絕對必要。驗證讓你多一個機會確認,你的工作已經準備就緒,可以分享給其他團員,以及:
  • 更簡單的開發和除錯
  • 跨瀏覽器的一致性,同時著眼現在和未來
  • 更快速的頁面載入
  • 無障礙性的部分實質審查
  • 正確地撰寫=只需寫一次
我推薦用 W3C CSS 驗證服務



壓縮工具
假如你和你的團隊關心檔案大小、頁面下載時間和頻寬(誰不會呢?),那麼你可以考慮針對 CSS 使用壓縮工具。這些工具可以做許多事,從縮短 16 進位色彩值到移除註解。下面是一些值得考慮的方案:
我不建議在開發階段的檔案使用壓縮工具,雖然它減少了檔案大小,但也減少你和團隊閱讀和處理 CSS 檔案。所有的註解都消失了。所有的空白都移除了。你再也有沒有方便工作的 CSS 檔案。讓使用壓縮工具成為上線前的最後一步。



冰山一角
這篇文章談論到的只是一些基礎的實踐,幫助你和你的團隊在處理 CSS 時可以更快樂、更有效率。還有許多文章你可以追讀,讓你日後 CSS 能更臻完美。假如你的好奇心被誘發了,那麼我建議你讀下面這些文章:


遵循黃金法則
無論你是和內部的團隊,或是面對廠商、外包商,甚至你自己就是一人團隊,這些 CSS 實踐會幫助你建立基礎規則,讓你成為一個好的 CSS 團隊的一員,進而節省時間和挫折感。
你需要做的,只要回想起小時候聽過的黃金法則,並牢牢地記住:善待你的 CSS,如同你希望別人怎麼對待它。


0 意見:

張貼留言

若對於本篇文章有任何批評指教或鼓勵建議,歡迎您留言讓我知道...