英文原文:Be a CSS Team Player: CSS Best Practices for Team-Based Development,編譯:w3cplus – D姐
你有過多少次接手別人開發過的專案,卻發現作者的程式碼思路一團糟嗎?或是你跟幾個團隊成員合作開發,他們每個人都有自己書寫程式碼的方式嗎?或是你重新回顧你多年前開發的專案,不記得當初是怎麼想的?
我總是遇到這種事情。事實上,我最近在修復供應商提供facepalm-inducing的css上花費了將近300個小時。這300個小時,使我充滿了挫敗感,不僅是因為我自己,還有我的團隊成員的原因。而且他佔用了本應該花費在新專案上的寶貴時間和資源
如果供應商在他的css中已經遵循了一些基本的指導方針。那麼將會為他節省寶貴的時間和金錢,更不用說我會已更好的狀態去對待他。在本文中,你將學習書寫CSS的最佳實踐來幫助你避免不一致和冗餘;實際上,這樣制定標準,簡化了團隊開發的工作。
結構化
書寫好的css的基礎是有良好的結構。這樣的css可以幫助我以及任何將來要更新這段程式碼的人,更好的理解並快速定位到要找的樣式上。
在開始寫樣式前,我先定義了一個css檔案結構,根據頁面中不同內容部分劃分的區塊。通常,這些結構是每個網站通用的:
1.Header
2.Navigation
3.Main content
4.Sidebar
5.Footer
在我的樣式檔案裡,我新增了必要的註釋,以標明每個部分的樣式從哪裡開始
1 2 3 4 5 6 |
/*---GLOBAL---*/ /*---HEADER---*/ /*---NAV---*/ /*---CONTENT---*/ /*---SIDEBAR---*/ /*---FOOTER---*/ |
注意第一個註釋global的部分,他不是針對於網站的特定內容,而是針對網站上的通用樣式,例如佈局結構,以及標題、段落、列表和連結等基礎樣式。
在樣式頭部設定通用的樣式,有助於全站更好的繼續共有樣式,並在需要時覆蓋即可。
越多的css就需要越多的組織
在建立超大型的網站,處理相當多的css時,我就會給每個區塊裡新增二級註釋。例如,在global裡我定義這樣的二級結構分類:
1 2 3 4 5 6 7 8 9 10 11 12 |
/*---GLOBAL---*/ /*--Structure--*/ /*--Typographic--*/ /*--Forms--*/ /*--Tables--*/ /*---HEADER---*/ /*---NAV---*/ /*--Primary--*/ /*--Secondary--*/ /*---CONTENT---*/ /*---SIDEBAR---*/ /*---FOOTER---*/ |
同樣你也看到了我給NAV也新增了二級註釋,分別為主導航和次導航。
事實上,對於很少css的小型網站,我通常是不使用二級註釋的。但是對於大型的css檔案,二級註釋被證實是很管用的。
自由格式化
你使用的註釋格式完全取決於你。以上你看到的例子是我和我的團隊很鍾愛的方式。也有些人喜歡用兩行定義他們的註釋格式:
1 2 |
/* HEADER ------------------------------*/ |
另一些人使用特殊字元如‘=’,作為搜尋字元的標記:
1 2 |
/* =Header ------------------------------*/ |
一些人不使用二級註釋,他們用一種完全不同的結構,不是根據頁面內容劃分,而是用元素的型別劃分如:headers,images,lists等等。關鍵是用你喜歡的格式去定義並一直這麼使用。
想根據內容元素劃分?沒問題。想要小寫註釋,那就去做。不想使用二級註釋縮排?那就不用.不喜歡連字元想用時間?ok。你只需要做對於你和你的團隊最有意義的事情就好。
交流注釋用法
我們已經瞭解了註釋的結構,但是你應該就這如何使用註釋的問題跟你團隊的同事交流一下。
什麼時間,誰做了什麼
作為團隊成員的一份子,很有必要在團隊成員之間交流已經寫好的css檔案的相關細節。在我的團隊裡,我們在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---*/ |
顏色值在開發階段很有用,節省你測試顏色和從其他樣式裡查詢的時間。你不需要知道這個十六進位制值是不是藍色,你只需要找到這個顏色值,然後複製貼上即可。
在我的團隊裡,我們在css檔案頭部新增通用的顏色值,要在所有樣式宣告和註釋前,摘要註釋後面新增。我們也嘗試保持關鍵字儘可能簡單方便維護,但是他到底有多複雜完全取決於你。
格式也全取決於你。你可以讓所有定義的顏色值放在一行顯示,也可以把他們分成多行顯示:
1 2 3 4 5 6 7 8 9 |
/*---COLORS Green #b3d88c Blue #0075b2 Light Gray #eee Dark Gray #9b9e9e Orange #f26522 Teal #00a99d Yellow #fbc112 ---*/ |
同樣,找到一個最好的有利於你需要的格式,一旦定義好就要保持他的一致性。
開發和除錯
有時候在我開發的過程中,不得不徘徊在我的css 和團隊其他成員之間。而這時註釋就派上用場了。當我有時冥思苦想為什麼css在ie下會有這樣的bug,我就只需要走開即可。
你或是你的同事做個筆記,包括可能的樣式,和沒有解決的困惑:
1 2 3 4 5 6 7 8 9 |
/*--//--Styling for link states is pending new changes from designer, please don't edit | EPL 03/23/10--\\--*/ a, a:link, a:visited { color:#0075b2; text-decoration:none; } a:hover, a:focus, a:active { color:#b3d88c; } |
1 |
為了讓他們與眾不同,我通常用一種不同於其他註釋的格式,同時讓他們儘可能的詳細。還是使用最適合你的格式。</span> |
不過記住,一旦你完成開發和除錯工作,這些註釋就沒有用了。他們既不跟你的工作有關,也不跟你的css有關,他們的存在只會增大你的檔案體積。
樣式重置
樣式重置已經很流行。他們出現在樣式檔案的頭部,用來設定html元素在跨瀏覽器顯示的基本樣式:
1 2 3 4 5 6 7 8 9 10 11 12 |
/*---RESET---*/ 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 { margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } |
以上的例子摘自Eric Meyer的重置文件,這個我也經常用。但是我傾向於去掉我用不到的標籤,我也建議你這樣做。比如我的團隊構建的網站裡面幾乎沒有<kbd>,也沒有<iframe>,<applet>或是包含以上的一些元素。
所以,我去掉這些元素選擇器。雖然在頁面載入或是檔案體積上只有很小的不同,但是我感覺這樣有助於,避免團隊成員間對於不使用的標籤的困擾。
如果我不想要覆蓋瀏覽器的內建樣式,我也可以編輯重置樣式表,例如如何處理無序列表。在這種情況下,我確保這些元素不包含在樣式表宣告裡。
不過,我應該澄清一下,css重置並不適用於所有人。你有很多不使用他的理由,這由你決定。如果你要重置樣式,要保持你的重置樣式表儘量乾淨和特殊。
命名約定
最頭疼的事情之一是,遇到其他人寫的css,而且是定義的類名和id名毫無意義的那種。例如像下面這樣:
1 2 3 4 5 6 |
.f23 { background: #fff; border: 1px solid #ff0; font-weight: bold; padding: 10px; } |
我根本不知道.f23是什麼意思。甚至更糟的是都沒有任何形式的註釋。我不知道.f23代表什麼內容。是標題?主要內容?還是導航?
這種情況,尤其是對於大型網站,就可能浪費大量的時間去查詢出現這個類名的標籤位置。如果作者用一個約定好的名字命名,如那些有意義的,那些基於內容的樣式的:
1 2 3 4 5 6 |
.alert { background: #fff; border: 1px solid #ff0; font-weight: bold; padding: 10px; } |
如你所見,類名.alert提供的上下文資訊要比用一個隨機陣列成的類名提供的資訊多。
不僅僅是上下文,有語意的命名還可以節約時間。考慮到一個公司品牌的頻繁更換,如果你開發的css使用表現的類名而不是語義化的類名和id名,那麼在尋找、維護css時,你將比預期花費更多的時間。
例如,如果你給網站上一塊內容,定義一個bluebox的類名,使用了公司logo的藍色基調。然後公司重組了,他們現在用紅色基調的logo,這時你的.blueBox就沒有意義啦。所以你不僅需要更新樣式表的十六進位制顏色值,還需要修改標籤中的所有引用到blueBox的地方。
相反如果你用callOut作為類名(或是同樣有意義的名字),你會省去手頭的很多工作量。
類名濫用
在css 的使用中,我傾向於能少則少的原則。不能因為你可以給每個元素指定類名,就意味著你就應該給每個元素指定類名。
在我修復供應商糟糕的css過程中,發現類名被濫用了,出現在許多本來不需要的地方。例如每一個lable標籤就定義一個lable類名,每一個form就定義一個form。但是我們的設計和結構中只需要給一個form元素設定樣式,它裡面也只包含一個label元素。
1 2 3 4 5 6 7 8 9 10 11 12 |
form.form { float: right; margin: 0; padding: 5px; } label.label { clear: both; float: left; text-align: right; width: 145px; } |
由此產生的css本身和他造成的冗餘並不可怕,可怕的是他造成的困惑。作為一個設計師看到了這個form類,可能猜想是不是其他樣式表裡也定義了叫form的類名,然後去查詢根本不存在的樣式,這就是我時間浪費的原因。
類名不等於特異性
上面只是一個簡單的例子。一個我遇到的有關類名更瘋狂的例子是渴望給予元素特殊性
1 2 3 4 5 6 |
<div id="feature"> <ul> <li><a href="#newServices">New Services</a></li> <li><a href="#newProducts">New Products</a></li> </ul> </div> |
注意到tabs的類名應用到了上面結構中的每一個標記?導致如下的css目錄列表:
1 2 3 4 5 |
div.tabs ul.tabs li.tabs { float: left; font-weight: bold; padding: 3px; } |
對於li最簡便的解決方法應該是這樣:
1 2 3 4 5 |
#feature li { float: left; font-weight: bold; padding: 3px; } |
如果你的元素定義樣式不需要類名,那就不要用。用的太多類名,不僅使你的結構和css很臃腫,也失去了他們在css 中的意義。
你也許注意到了在最後的例子中,我僅使用了# feature作為選擇器而不是div#feature。只有在為了區別其他選擇器的情況下,新增div才合適,否則只會給你的團隊帶來負擔。而且儘量少用特殊的宣告,也為日後覆蓋任何樣式提供方便。
多類
最後一點,我不喜歡多類,你也許還有印象。雖然我不提倡使用不必要,多餘的類名,但是對於通過多類保持元素表現的共用,我可是一個忠實的粉絲,然而可能有一些理解的不同之處:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.announcement { background: #eee; border: 1px solid #007b52; color: #007b52; font-weight: bold; padding: 10px; } .newsAnnouncement { background: #eee; border: 1px solid #007b52; color: #007b52; float: right; font-weight: bold; padding: 10px; } |
上面的兩個宣告,除了.newsAnnouncement多了一個浮動外,都完全一樣。所以我大可像下面這樣而不是重複寫相同的樣式:
1 2 3 4 5 6 7 8 9 10 11 |
.announcement { background: #eee; border: 1px solid #007b52; color: #007b52; font-weight: bold; padding: 10px; } .floatR { float:right; } |
然後給我的新聞內容新增兩個類名
1 |
<div class="announcement floatR"> |
但是且慢,我不是說過要根據約定好的名字而不是根據表現命名嗎?沒錯,但是凡事總有個例外。
是的,.floatR是一個表現類名,但是他適用於這種情況,而且可以用於其他需要多類的情況,所以這是我的團隊經常使用的方法。
分組選擇器
在我的300個小時的折磨裡,遇到的另一個問題是完全相同的樣式出現在多個樣式表裡,而唯一的區別就是宣告他們的選擇器不同:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#productFeature { background: #fff; border: 1px solid #00752b; float: left; padding: 10px; } #contactFeature { background: #fff; border: 1px solid #00752b; float: left; padding: 10px; } #serviceFeature { background: #fff; border: 1px solid #00752b; float: left; padding: 10px; } |
這不僅使得css檔案體積過於臃腫,也使維護成了噩夢。解決方法就是合併他們成一個樣式宣告:
1 2 3 4 5 6 |
#productFeature, #contactFeature, #serviceFeature { background: #fff; border: 1px solid #00752b; float: left; padding: 10px; } |
現在如果要更新樣式只需要修改一個宣告而不是三個。
一行還是多行書寫?
本文中出現的所有css例項都是用的多行的格式,每一對屬性和值佔單獨一行。這個是廣泛使用的約定,不僅是在css檔案中,也多出現在書裡和文章裡。許多人認為他的可讀性很好,這也就是什麼我在本文使用他的原因。
然而在和團隊的工作中,尤其是大型的css檔案,我是將樣式寫成一行:
1 |
.alert {background: #fff; border: 1px solid #ff0; font-weight: bold; padding: 10px;} |
就我個人和我的團隊而言,覺得單行的可讀性更好。當你查詢css時多行樣式就變得很麻煩,相比較而言單行查詢更容易。
對於你和你的團隊,選擇最合適你的團隊的格式,並一直使用他。
需要依照字母順序排列嗎?
一些人建議將每個宣告按照字母表的順序排列,方便快速查詢一個屬性。以前我對這樣的事情並不在意,但是經過處理供應商混亂的css之後,我意識到將一些思想應用到樣式宣告的組織中是個很好的主意。
儘管我發現按照字母表排序很有用,但是我還是會根據上下文來組織哪些屬性放在一起。比如,我喜歡將所有的盒模型屬性放在一起。如果我使用了絕對定位,我就把這些屬性放在一起:
1 2 3 4 5 6 7 8 |
#logo { border: 1px solid #000; margin: 0; padding: 0; position: absolute; top: 5px; right: 3px; } |
這裡沒有對錯之分,僅僅是決定用哪種屬性的排序並一直用它就好了。
使用簡寫
使用css簡寫一直是認為可以提高你的css水平的方法。他同時也適用於團隊,它不僅可以有助於瀏覽,而且可以方便設定大家遵守的標準。這樣就減少了花費在思考和書寫樣式的時間。
0值
如果你使用0值,沒有必要給他指定單位:
1 |
margin: 2px 3px 0px 4px |
變成
1 |
margin: 2px 3px 0 4px |
顏色模式
十六進位制顏色值如果是由三對陣列成,可以從每組中抽出一個陣列成該顏色值的簡寫:
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 |
字型屬性
多條字型屬性可以合併成一條
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 |
背景色屬性
背景屬性也是可以合併的
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% |
請注意最後兩個例子,字型和背景屬性。屬性值的宣告順序要按照w3c的標準來。
驗證,驗證,再驗證
雖然一些人認為驗證css需要指定一個很好的驗證規則,這一點我不強求但是他絕對是有要求的。驗證能夠確保你的工作,是否準備好分享給團隊的其他成員,所以他應該滿足下面要求:
1.容易開發和故障排除
2.保證現在和未來的瀏覽器顯示一致
3.保證頁面的快速載入
4.作為可訪問性的一部分
5.把他正確的寫出來
我建議使用W3C CSS驗證服務。
壓縮工具
如果你的團隊關心檔案大小,頁面載入和頻寬的話,你應該考慮使用一個壓縮工具。它主要是用來去除不必要的註釋,空格。這裡有一些壓縮工具可以考慮:
4.CSS Tidy
我不建議在開發的過程中壓縮檔案,因為壓縮可以減小你的檔案大小,同時也削弱了你和團隊之間協同開發和處理css 的能力。因為他去掉了具有可讀性的所有註釋和空格,所以應該把壓縮作為產品上線的最後一道工序。
冰山一角
本文中提到的只是少數基礎實踐,他們可以幫助你和團隊高效的工作。遵循這些準則可以進一步完善你的css。如果你很感興趣的話,我推薦你閱讀下面的文章:
1.Different Ways to Format CSS
2.Unique Pages, Unique CSS Files
3.Single-line vs. Multi-line CSS
4.CSS Property Order Convention
5.On HTTP: Page Load Times, Multiple File Requests and Deferred JavaScript
7.Efficient CSS with shorthand properties
8.CSS Sprites: What They Are, Why They’re Cool, and How To Use Them
遵守黃金定律
不管你是工作在一個團隊中,還是作為外包或是作為團隊的唯一成員,這些css準則將為你日後成為一個優秀的團隊成員打好堅實的基礎,它不僅節約你的開發時間,也避免了不必要的沮喪情緒。
譯者手語:初次翻譯前端技術博文,整個翻譯依照原文線路進行,並在翻譯過程略加了個人對技術的理解。如果翻譯有不對之處,還煩請同行朋友指點。謝謝!