英文原文:
http://www.456bereastreet.com/archive/200601/css_3_selectors_explained/
中文翻譯:
http://www.dudo.org/article.asp?id=197
注:本文寫於2006年1月,當時IE7、IE8和Firefox3還未發行,文中所有說的浏覽器支持均未包括這三個版本的浏覽器。在IE8和Firefox3中,文中的大部分選擇符已經被支持[dudo注]
在2005年的9月和10月,我先後發表了幾篇關於CSS2.1中選擇符的介紹文章。大體看來那幾篇文章中介紹過的大部分選擇符都已經可以在像Mozilla/Firefox,Safari和Opera等現代浏覽器中使用了。我們現在要做的就是等待Internet Explorer盡快趕上來,那我們就可以盡情地使用CSS2.1中的選擇符了。好在Internet Explorer在其第7個版本中已經在盡力追趕了,至少在某些擴展方面。
如果我們再向前看一點,在CSS3中還有功能更加強大的選擇符等待我們去發掘和使用。CSS3中的很多選擇符已經在現代浏覽器中得到很好的應用(IE8.0中也已經部分地支持了CSS3,dudo注),但是這些基本功能上的支持還遠遠不能滿足開發者使用的要求。但是在某些情況下使用他們可以帶來很好的超前體驗,因此我認為了解一下CSS 3新增選擇符是如何使用還是有益處的。
本文中對選擇符描述主要是參考了《2005年12月15日W3C制定的選擇符草稿》。草稿中講到的新的選擇符可能會在CSS的第3個版本中出現,但是也可能會出現在其他語言中。如果你是幾個月前甚至是幾年前讀過這篇草稿,那麼現在你應該再去看一下是不是已經出現了最新版本了。
這裡我不打算去解釋CSS選擇符工作的基本原理。如果你想重要復習一下的話,最好從《細說CSS2.1中的選擇符》開始。
首先,快速浏覽一下CSS3中新增的選擇符:
CSS3選擇符語法概覽:
選擇符類型
表達式
描述
子串匹配的屬性選擇符
E[att^="val"]
匹配具有att屬性、且值以val開頭的E元素
子串匹配的屬性選擇符
E[att$="val"]
匹配具有att屬性、且值以val結尾的E元素
子串匹配的屬性選擇符
E[att*="val"]
匹配具有att屬性、且值中含有val的E元素
結構性偽類
E:root
匹配文檔的根元素。在HTML中,根元素永遠是HTML
結構性偽類
E:nth-child(n)
匹配父元素中的第n個子元素E
結構性偽類
E:nth-last-child(n)
匹配父元素中的倒數第n個結構子元素E
結構性偽類
E:nth-of-type(n)
匹配同類型中的第n個同級兄弟元素E
結構性偽類
E:nth-last-of-type(n)
匹配同類型中的倒數第n個同級兄弟元素E
結構性偽類
E:last-child
匹配父元素中最後一個E元素
結構性偽類
E:first-of-type
匹配同級兄弟元素中的第一個E元素
結構性偽類
E:only-child
匹配屬於父元素中唯一子元素的E
結構性偽類
E:only-of-type
匹配屬於同類型中唯一兄弟元素的E
結構性偽類
E:empty
匹配沒有任何子元素(包括text節點)的元素E
目標偽類
E:target
匹配相關URL指向的E元素
UI元素狀態偽類
E:enabled
匹配所有用戶界面(form表單)中處於可用狀態的E元素
UI元素狀態偽類
E:disabled
匹配所有用戶界面(form表單)中處於不可用狀態的E元素
UI元素狀態偽類
E:checked
匹配所有用戶界面(form表單)中處於選中狀態的元素E
UI元素狀態偽類
E::selection
匹配E元素中被用戶選中或處於高亮狀態的部分
否定偽類
E:not(s)
匹配所有不匹配簡單選擇符s的元素E
通用兄弟元素選擇器
E ~ F
匹配E元素之後的F元素
如果對上面的描述還不是很清楚的,請不要擔心。本文下面的部分將會對他們進行更加詳細的講解,並且提供例子來演示他們是怎麼使用的。
子串匹配的屬性選擇符
這一組的選擇符都新加的,他允許開發者對屬性中的子字符串來進行匹配。
假設HTML文檔中包含下面的代碼結構:
<div id="nav-primary"></div>
<div id="content-primary"></div>
<div id="content-secondary"></div>
<div id="tertiary-content"></div>
<div id="nav-secondary"></div>
通過使用子串匹配的屬性選擇符就可以找到文檔中這些結構性的特定組合。
下面的規則將為id以“nav”開頭的div元素設定背景顏色:
div[id^="nav"] { background:#ff0; }
上例中選擇符會匹配div#nav-primary和div#nav-secondary。
要找到id以primary結尾的div元素,可以使用下面的規則:
div[id$="primary"] { background:#ff0; }
這時選擇符將匹配div#nav-primary和div#content-primary。
下面的規則將會匹配到id中含有content子字符串的的div中:
div[id*="content"] { background:#ff0; }
受影響的元素有:div#content-primary、div#content-secondary和div#tertiary-content。
子串匹配的屬性選擇符已經在最新版本的Mozilla、Firefox、Flock、Camino、Safari、OmniWeb以及Opera中可以使用,但是如果IE中還不支持的話,我們最好還是先不要使用他們(作者在寫這篇文章時IE還在開發中,如今IE7、IE8都支持這些選擇符,dudo注)。
目標偽類
含有識別標識的url(一個#後面緊跟錨點名稱或者元素的id)指向的是文檔中的特定元素。鏈向其他目標元素的這些元素就可以使用:target偽類來修飾它。如果當前的URL中沒有任何的片斷識別標識,:target偽類將不會匹配任何元素。
還是以上面提到的代碼結構為例,如果URL中包含content-primary標識時,現在的規則將會在他外圍增加一個邊框:
div#content-primary:target { outline:1px solid #300; }
URL是類似這樣的形式的:
http://www.example.com/index.html#content-primary。
基於Mozilla和Safari的浏覽器已經支持:target偽類。
UI元素狀態偽類
:ENABLED偽類和:DISABLED偽類
在浏覽器允許改變表單控件外觀的前提下,:enabled偽類和:disable偽類允許開發者指定用戶界面中可用和不可用元素(表單元素)的顯示樣式。下面的規則將會根據單行輸入框是否可用設定不同的背景顏色:
input[type="text"]:enabled { background:#ffc; }
input[type="text"]:disabled { background:#ddd; }
:CHECKED偽類
:checked偽類允許開發者為處於選中狀態的checkbox和radio設定樣式。當然這也要在浏覽器允許改變表單控件外觀的條件下。下面的CSS規則將會使選中的radio和checkbox元素顯示一個綠色邊框:
input:checked { border:1px solid #090; }
UI元素狀態偽類目前可以在Opera和基於Mozilla的浏覽器中使用。
要注意的是,許多浏覽器對於開發者對表單控件樣式的改變有著嚴格的限制。更多關於這方便的內容可以我的兩篇文章:《樣式化表單控件》和《樣式化更多表單控件》。
結構性偽類
結構性偽類允許開發者根據文檔樹中表明的結構來指定元素,而這些使用簡單選擇符或者是混合選擇符都無法做到。結構性偽類功能十分強大,但是不幸的是現代浏覽器僅提供了有限的支持。
:ROOT偽類
:root偽類指向的是文檔的根元素。在HTML中,文檔的根元素始終是HTML,也就是說現在的兩條規則其實是一樣的(大體上說來:root要比html更專業點)。
:root { background:#ff0; }
html { background:#ff0; }
:NTH-CHILD()偽類
:nth-child()偽類指向的元素在文檔樹中有一定數量的兄弟元素存在。其中括號內的參數,可以是一個數字,也可以一個關鍵字或者一個公式。
數字b指是的第b個子元素。下面的規則將會應用到父元素下所有p元素中的第三個中:
p:nth-child(3) { color:#f00; }
關鍵字odd(奇數)和even(偶數)可以用來匹配序號為奇數或者是偶數的子元素。第一個元素的序號為1,因為下面的規則將會匹配第1、3、5...了子元素p:
p:nth-child(odd) { color:#f00; }
下面的規則則匹配第2、4、6...個字元素p:
p:nth-child(even) { color:#f00; }
表達式an+b可以用來創建更加復雜的循環模式。在表達式中,a代表步長,n是一個從0開始的計數器,b代表偏移量。其中,所有的數值都必須是整數(這裡,n是從0開始的,和js等中的循環不同的是,至於到多少結束取決於元素的個數決定,如文檔中有20個元素,3n(n=1,2...)就會分別選擇第3、6、9、...18個元素,n此時為6 ,dudo注)。為了更好理解如何使用表達式我們先看幾個代碼實例:
下面的規則將會匹配序號數為3的倍數的所有p元素。在第一行中,b等於0,因此可以忽略不寫(見第二行):
p:nth-child(3n+0) { color:#f00; }
p:nth-child(3n) { color:#f00; }
偏移量可以用來指定樣式的循環是從哪個元素開始應用的。如果有一個20行的表格,我們希望從第10行以後的奇數行開始使用不同的背景顏色,就可以使用下面這條規則:
tr:nth-child(2n+11) { background:#ff0; }
由於n是從為開始的,因此第一個受影響的tr元素的序號是11(2*0+11=11,dudo注)。接下來就是第13行(2*1+11=13)再接下來就第15行(2*2+11=15),以此類推。
更詳細介紹請參照CSS 3選擇符中的《nth-child()偽類》。
那麼,對於這樣有用的一個選擇符又有哪些浏覽器支持它呢?很糟糕,據我所知,沒有一個浏覽器支持這個選擇符甚至沒有浏覽器支持nth類的選擇符。如果有的話請幫我指正(Firefox3和IE8目前是否支持?dudo)
:nth-of-type()
:nth-of-type()偽類和nth-child()偽類找使用方法十分相似,只不過他匹配的是規則中指明類型的元素。下面的規則將會匹配每個屬於父元素中第三個子元素的p元素(屬於第3個子元素的p在一個該當中可能會有很多,只不過他們位於不同的父元素下,dudo注):
p:nth-of-type(3) { background:#ff0; }
當你想確定是否已經指向了第三個p元素,這種方法會很有用。開始你可能覺得這和使用nth-child效果是一樣的,但是nth-child(3)會把所有的子元素都計算進來,因此結果可能就會不一樣,除非p所有的所有兄弟元素也都是p元素。
:nth-of-type偽類目前還沒有浏覽器支持。
:nth-last-of-type偽類
:nth-last-of-type偽類指向的元素在其後還有若干同類型的元素。和:nth-last-child偽類一樣,它是從最後一個子元素向回數的。下面的規則將會匹配到倒數第二個兄弟元素p中(注意:是兄弟、同級別的節點):
p:nth-last-of-type(2) { background:#ff0; }
:nth-last-of-type()目前還沒有浏覽器支持。
:last-child偽類
:last偽類指向的是父元素中最後一個子元素。它和:nth-last-child(1)效果是一樣的。下面的規則匹配所有屬於父元素中最後一個子元素的p:
p:last-child { background:#ff0; }
:last-childe偽類可以在基於Mozilla的浏覽器中使用。Opera不支持:last-childe偽類,在Safri中存在bug(上面的規則會匹配到所有的p元素)。令人稀奇是的它可以在OmniWeb(測試版本5.1.1)中正常使用,盡管這個浏覽器是基於Safari的。這可能是因為Apple WebKit最新版本的回歸,因為OmniWeb使用的WebKit通常要比Safari版本稍微低一點。
:first-of-type偽類
:first-of-type偽類指向同類型元素中的第一個元素。它和:nth-of-type(1)是一樣的。
p:first-of-type { background:#ff0; }
:first-of-type偽類目前還沒有浏覽器支持。
:last-of-type偽類
:last-of-type偽類指向同類型元素中的最後一個元素。它和nth-last-of-type(1)是一樣的。
p:last-of-type { background:#ff0; }
:last-of-type偽類目前還沒有浏覽器支持。
:only-child偽類
:only-childe偽類指向的是那些父元素中再沒有其他任何子元素的元素。它和:first-child:last-child或者:nth-child(1):nth-last-child(1)是一樣的(後者不夠專業、簡明)。
p:only-child { backgound:#ff0; }
:only-childe偽類目前可以在基於Mozilla的浏覽器中使用。在Safari似乎被解釋成了:first-child(上面的規則會被匹配到文檔中所有第一個子元素p中)。
:only-of-type偽類
:only-of-type偽類指向的是那些父元素中再也沒有與之類型相同的子元素。這和:first-of-type:last-of-type或者:nth-of-type(1):nth-last-of-type(1)相同(後者專業性不夠)。
p:only-of-type { background:#ff0; }
:only-of-type偽類目前還沒有浏覽器支持。
:empty偽類
:empty偽類指向沒有任何子元素的元素。其中包括text節點,因此下面的示例只有第一行是空元素。
<p></p>
<p>text</p>
<p><em></em></p>
下面的規則只匹配第一行的p元素:
p:empty { background:#ff0 }
:empty偽類目前被基於Mozilla的浏覽器支持。Safari會錯誤地把樣式應用到所有指定的元素中去。
否定偽類
否定偽類寫成:not(s),參數s為簡單選擇符。它指向的是除簡單選擇所指向的元素以外的所有元素。例如,下面的CSS將會指向所有不是p的元素:
:not(p) { border:1px solid #ccc; }
否定偽類目前只有基於Mozilla的浏覽器支持。
::selection偽類
::selection偽類匹配指定元素中處於選中或者高亮狀態的部分。其中一個應用就是用它來控制選中文本的樣式。
下面的規則會使選中的文本顏色變為紅色:
::select { color:#f00; }
::selection偽類目前可能基於Safari的浏覽器支持。但是在使用上會出現不可預料的情況,因此Safari還需要一點改進。基於Mozilla的浏覽器要使用-moz-prefix: ::-mozi-selection來實現。這種prefix可能最終會被去掉。
通用兄弟元素選擇器
通用兄弟元素選擇器通過兩個簡單選擇符通過波浪號(~)分隔組成。它匹配第二個簡單選擇符中所匹配的元素,而且與第一個簡單選擇符中匹配的元素要出現在他的前面。這兩個元素必須具有同一個父元素,但是第二個元素不一定必須緊跟在第一個元素之後。這條CSS規則將會匹配所有p元素之後ul元素:
p ~ ul { background:#ff0; }
通用兄弟元素選擇器目前有Opera和基於Mozilla的浏覽器支持。
亟需更好的浏覽器支持
部分CSS 3選擇符已經被廣泛支持。但是,大部分非常有用的選擇符在現代浏覽器中或者未被支持或者使用受到限制。這就使得本文中介紹的很多選擇符在今天的Web或多或少失去了用武之地。但是不必害怕去嘗試它,你仍然可以在支持他們的帶來超前體驗的高級浏覽器中使用他們。
[附件]CSS3選擇符在現在浏覽器(Firefox 2、Firefox 3、InternetExplorer 7、Internet Explorer 8、Oper9.27)中的支持程度(dudo驗證,請指正!)
_________________IE 7________IE8________FF2_________FF3______Opera9.27
E[foo^="bar"]______Y__________Y__________Y__________Y__________Y
E[foo$="bar"] ______Y__________Y__________Y__________Y__________Y
E[foo*="bar"] ______Y__________Y__________Y__________Y__________Y
E:root____________ N__________N__________Y__________Y__________Y
E:nth-child()_______ N__________N__________N__________N__________N
E:nth-last-child()____ N__________N__________N__________N__________N
E:nth-of-type()_____ N__________N__________N__________N__________N
E:nth-last-of-type()__ N__________N__________N__________N__________N
E:last-child_________ N__________N__________Y__________Y__________N
E:first-of-type______ N__________N__________N__________N__________N
E:only-child________ N__________N__________Y__________Y__________Y
E:only-of-type______N__________N__________N__________N__________N
E:empty__________ N__________N__________Y__________Y__________N
E:target___________N__________N__________Y__________Y__________N
E:enabled_________ N__________N__________Y__________Y__________Y
E:disabled_________ N__________N__________Y__________Y__________Y
E:checked_________N__________N__________N__________N__________Y
::selection_________N__________N__________N__________N__________N
not()_____________N__________N__________Y__________Y__________Y
E ~ F_____________Y__________Y__________Y__________Y__________Y