樣式表
來自positioniseverything的How To write Efficient CSS是篇淺顯易懂的CSS最佳化技術教學文章,實用性強,文字優美,非常經典,曾經JJGOD有翻譯過,但是連結已經失效,自己也沒有儲存,所以乾脆用自己的風格翻譯出來,如果能達到JJGOD的翻譯水準將是我的無上榮幸。儘管我努力試圖保留原文作者的原汁原味,但是在翻譯過程中發現,作者使用的生動的詞句直譯成中文反而並不生動,為此加入自己的語氣和用詞習慣,這樣應該會令譯文重新恢複“生動”:)
水平有限,如有紕漏懇請撥冗斧正......
效率的好處
CSS最受追捧的優點就是減小頁面體積,從而減少了下載時間,無論是在頁面第一次被下載時,還是此後直接從緩衝中載入。事實的確如此,但是,這個在頁面首次被下載過程中節省下來的體積往往又有很大一部分被浪費掉了,原因就是極度冗餘的樣式表代碼。
好吧,一切都結束了,讓我們重新開始。你將學習一些高效的樣式表編寫“密技”,開始對你的樣式表敲骨吸髓榨乾到最後一滴汁。當然,你不可能藉此節省“巨大”的頁面體積,不過,對於那些在激烈的競爭中求生存的網站,省一個位元組是一個位元組,這些節省的位元組對他們而言是極具價值的。
有這麼幾個範圍可以進行“位元組瘦身”,包括簡寫屬性、多重聲明、使用預設值、屬性繼承和空白的處理。
簡寫屬性
在如何設定頁面邊距為零(Zeroing page margins)一文談及了幾個CSS簡寫屬性,不過關於這個主題仍然有很多可以說的。
常用的簡寫屬性包括:
- font — 字型,控制"font-size"(字型尺寸)、"font-weight"(字型磅數)、"line-height"(行高)等
- background — 背景,控制元素的背景、定位、重複等
- list-style — 列表樣式,設定清單項目符號的屬性
- margin — 邊距,定義盒裝容器各條邊框旁留出的空白的寬度
- border — 邊框,定義盒狀容器各條邊框的樣式屬性,此處會涉及到另幾個涉及邊框的簡寫屬性
- padding — 內邊距,定義盒狀容器各條邊框內側留出的補白寬度
以上清單項目可以直接連結到W3C CSS 2 specifications中相關的內容章節。
例如,font(字型)屬性是一次性同時設定font-style(字型樣式)、font-variant(字型變體)、font-weight(字型磅數)、font-size(字型尺寸)、line-height(行高)和font-family(字型組)的簡寫屬性。然而,並不是所有這些屬性都必須在簡寫屬性中同時用到。當簡寫格式中的某些值被省略時,每個“失蹤”的屬性實際上都被指定使用它的預設值,這些值都可以在W3C specifications的font property(字型屬性)內容部分中找到。如果在一個樣式表檔案中大量使用了字型相關的樣式控制屬性,那麼使用這個簡寫屬性將能顯著縮減樣式表的體積。
background(背景)和list-style(列表樣式)屬性也有類似的作用。列表中剩下的幾個簡寫屬性涉及到一個CSS盒狀容器的四條邊框,和前幾個屬性情況有所不同。
盒狀容器邊框的簡寫屬性
任何一個區區塊層級元素(divs—區塊、tables—表格、lists—列表、paragraphs—段落,等等)的四條邊框都有各自的margins、borders和padding屬性,可以各自單獨設定它們的寬度。就拿borders來說,每條邊框都可以獨立分配border-style(邊框式樣)和border-color(邊框顏色)。要是將所有這些屬性統統拼字出來,乖乖,單這一條規則集就夠冗長的了!使用簡寫規則可以極大地減少工作量。
時鐘
假如盒狀容器四條邊框的某個邊框屬性都一樣,那樣的話只要使用基本的簡寫屬性就可以了,比如這樣寫:
margin: 5px;
border-width: 5px;
padding: 5px;
注意: 必須設定border-style(邊框式樣)才能顯示邊框。為此我們可以定義border-style屬性或在border屬性中設定式樣。僅僅使用border-width屬性是不能顯示邊框的。
可是,假如出現其中幾條邊框的值並不相同的情況,這時候,一種我們稱之為“時鐘”的CSS特性開始起作用了。讓我們把一個盒狀容器想象成一個鐘面。當指標向上直指,它們所指的相當於盒狀容器的頂邊,也正是簡寫屬性的第一個值。接下來是三點鐘的位置,相當於盒狀容器的右側邊。然後是六點鐘位置,相當於盒狀容器的底邊,最後九點鐘方位指代左側邊。
來看個例子。我們想在頁面上放一個盒狀容器,它的頂邊距寬10px、右邊距寬5px、底邊距寬3px、沒有左邊距。那麼用margin簡寫屬性可以這麼寫:
margin: 10px 5px 3px 0;
在聲明屬性時,這些屬性值之間必須用也只能用空格分隔。並且,除非屬性值為零,否則每個值都必須標註單位。
注意一下邊距為零時值被定義成0,因為無論什麼值只要是零,單位就無關緊要。任何一種單位(px, em, %, 等)的零值等於任何其他單位的零值。
改型時鐘
當某幾條邊框相同時,邊框的簡寫屬性可以更大程度地濃縮。如前文所述,當所有邊框都一致時,所有邊框使用同一值,可是,假如頂邊和底邊一致,而右側邊和左側邊一致,這樣的情況下,邊距的代碼可以寫成如下這樣:
margin: 10px 5px;
這樣寫將頂邊和底邊的邊距設定成10px,兩側的側邊距為5px。還有一招,就是當頂邊和底邊不同而側邊一致的情況。頂邊距10px、左側和右側邊距5px、底邊距20px,我們就這麼寫:
margin: 10px 5px 20px;
這全都取決於簡寫屬性用到的值得數目以及次序。記住,一個值=所有的邊框;兩個值=頂/底邊框,兩側邊框;三個值=頂邊框,兩側邊框,底邊框;四個值=遵循鐘面原則。好了,不太難記吧?
邊框差異
border shorthand properties(邊框簡寫屬性)和padding(內邊距)同樣也可以使用這種“時鐘”簡寫方法。border-width,border-color,border-style和padding和margin(邊距)的操控方式相同。不過,border屬性還是有一點差異的。border屬性可以同時設定盒狀容器的四條邊框的border-width、border-style和border-color。
當四條邊框全都一樣時很好處理,但是如果他們不一樣呢?難道我們還要回到從前諸如border-top、border-right的日子嗎?好吧,也許可以。幸運的是,我們另高招。
譬如說盒狀容器各邊框的式樣和顏色都相同,唯獨寬度各不相同。最直接有效寫法是照常使用基本的border簡寫屬性定義border-width、border-style和border-color,然後單獨使用border-width屬性定義不同的邊框寬度來覆蓋前面的設定,象下面這樣:
border: 10px solid red;
border-width: 10px 5px 3px 0;
如果四條邊框的所有邊框屬性都各不相同,那麼這個辦法就派不上大用場了,不過這種情形畢竟不常發生。如果僅是border-style或者border-color屬性各有變化,那麼用這個辦法稍作修改就能像處理border-width那樣來處理這些屬性了。
接下來我們一起來看另一種情況,看看高效的CSS編寫方式有什麼不同。
多重聲明
譬如說我們有六個絕對位置的區塊(Dreamweaver中的層),它們全都一樣,所不同的是它們彼此隔開一定距離橫排在頁面頂部。由於它們的頁面定位不同,必須給它們取單獨的類名或ID,除此之外它們其餘的屬性統統一樣。
用排版編輯器的話或許會為每個ID單獨編寫樣式規則,包括所有的字型規則、文本規則、定位聲明等等。像這樣不停地重複那些完全一樣的規則看上去實在不是什麼明智之舉,不是嗎?沒錯。下面就是如何最大限度地精簡這些規則的方法:
#first {left: 0;}
#second {left: 100px;}
#third {left: 200px;}
#fourth {left: 300px;}
#fifth {left: 400px;}
#sixth {left: 500px;}
#first, #second, #third, #fourth, #fifth, #sixth {
position: absolute;
top: 0;
width: 75px;
font-size: .9em;
font-weight: bold;
text-align: center;
line-height: 1.4em;
background-color: silver;
color: navy;
padding: 5px;
border: 1px solid navy;
}
通過逐個列出這些相同區塊的ID,並用逗號緊跟一個空格來分隔這些ID,後面大段的樣式規則將同時應用於所有這六個區塊。顯而易見,如果每個ID都重複定義這些屬性,整個CSS就會臃腫不堪。這可能是唯一最有效減小樣式表體積的辦法了。
注意: 確保最後一個ID選擇符後面
沒有跟逗號,而應該像上面的多重ID規則集代碼樣本寫的一樣。有些瀏覽器仍舊能顯示這些區塊,但是有些就會將這個認作是代碼錯誤而不顯示任何一個區塊。
使用預設值
多數CSS屬性都有初始預設值,而當你為元素的這些屬性重新定義了值的時候,它們的預設值也就被覆蓋了。例如內邊距的各個屬性,padding-top、padding-right、padding-bottom和padding-left,它們的初始值都是0。如果不希望目標元素有內邊距,那麼內邊距屬性就可以省略不寫。
注意: 我們先前討論的簡寫屬性本身並沒有預設值。通常各個值都取自簡寫模型中所表現的單個屬性。雖然CSS 2 specification
Property Index(屬性索引)裡列出的預設值裡很多是
none或者
0,但瀏覽器通常自己會根據不同元素為某些屬性設定不同預設值的。
例如: Opera瀏覽器預設body元素的內邊距為8px。h1-h6標題和段落元素通常預設的邊距都不為零。不同的瀏覽器,為lists(列表)和list-items(清單項目)預設的內外邊距非零預設值也不盡相同。
屬性繼承
避免編寫冗餘代碼的另外一個辦法就是注意子項目從父元素那裡繼承下來的屬性。可以繼承的屬性著實不多,可其中很多還是不常用到的屬性,像voice-family。常用的可繼承屬性的列出來也沒幾個(按字母順序):
- color — 顏色
- font (and related properties) — 字型及相關屬性
- letter-spacing — 字距
- line-height — 行高
- list-style (and related properties) — 列表樣式及相關屬性
- text-align — 文本對齊
- text-indent — 文本縮排
- text-transform — 文本轉換
- white-space — 空白
- word-spacing — 詞距
在某些舊版瀏覽器中繼承特性存在很多問題,而現在的新版瀏覽器一般來說都能正確實現繼承。只要瞭解了哪些屬性可以繼承,你就又能少寫不少多餘代碼了。重申一下,要查閱完整的屬性列表請查看CSS 2 Property Index(CSS 2 屬性索引)。
空白的處理
這裡說的空白不是CSS裡那個有特定值的white-space屬性,這裡說的是樣式表檔案裡面本來就存在的空白間隔。這些個間隔來自於那些用於產生新行的分行符號,以及那些在單獨一行裡有助提高可讀性的空格。儘管移除這些間隔可以省出幾個位元組的體積,但是通常也省不了多少。
假如這些空隔被移除了,樣式表會變得晦澀難讀,更別提以後做修改了。如果工程明確要求刪除每一個多餘的位元組,那你最好建立一個方便閱讀的“主”樣式表檔案,然後複製一份,再把其中所有的空白移除,這份樣式表就是使用中的“現場版”樣式表。要是今後要修改的話,在那份易讀的主樣式表裡修改,再像上面那樣複製一份並移除空白,繼續作為“現場版”。
小心!有些空格是CSS編碼中必需的,要是這些空格被移除了,CSS規則也會跟著改變並導致一些意外結果的發生。W3C的規範說明中要使用了諸如"space separated,"(以空格間隔)這樣的措詞,那麼這些空格就是必需的。這種情況常見於簡寫屬性的各個屬性值之間。往往我們講到包含選擇符就講到
包含組合符,它就是一個空格,要是把選擇符裡所有的空格都移除,那可不是什麼好主意。也許移除空格這樣的活留給那些狂熱分子最適合不過了,是吧?
總結
至此你已經學習了如何使你的樣式表更簡潔經濟高效的幾種方法。經常使用這些技巧的好處不僅僅是節省樣式表體積、加快下載,更令樣式表常葆清爽整潔,通常易讀易懂的代碼也易於後期必要的修改維護。即便你是用排版編輯器來建立你的樣式表,你一樣可以用本文中所提及的這些方法來將你的“成品”編寫得更合理更高效!
Holly 'n John
e-mail
©positioniseverything
Last updated: July 3, 2004
Created November, 2003
Translated by
POPO
EVER on October 10, 2004
—————————— 全文完 ——————————
譯者注: 本文在翻譯過程中有幾點引起我的注意,主要是一些專屬名詞如何翻譯最為恰當,我原本也有看過不少國內的Web Standards相關的翻譯作品以及中文本土作品,其間對於一些名詞一直糾纏不清,各說一詞,我也就暫且不去管他們了,漢語博大精深,想要統一一個單詞往往不是件容易事,更何況本來就是“舶來”的術語。比如padding,有翻成“填充”的,有翻成“補白”的,還有翻成“補丁”,對於後二者我倒覺得可以接受,至少諧音可以方便洋文差的朋友記憶,不過我還是堅持把它翻成“內邊距”,因為這樣從表意上說最形象,padding本來就是邊框到內部文本的距離麼,不叫“內邊距”叫什麼。至於margin究竟是譯作“空白”還是“留空”或是“間隙”、“間隔”、“邊距”,哪個更好,我母親從前是做進階編輯的,她跟我說應該叫“白邊”,既然我已經把padding翻成“內邊距”,那麼看來margin也只能湊成一對地翻作“邊距”嘍。還有一個是box,見得最多的是翻成“盒模型”或“盒對象”,我也懶得去羅嗦什麼了。無論如何,只是一己之見,也就故妄譯之,但願沒有混淆視聽~~~