CSS是對網頁設計師可用的最強大的工具之一。使用它咱們能夠在幾分鐘內改變一個網站的界面,而不用改變頁面的標籤。可是儘管事實上,咱們每一個人也都意識到了它是有用的,CSS 選擇器遠未發揮它們的潛力,有的時候咱們還趨向於使用過多的和無用的class、id、div、span等把咱們的HTML搞的很凌亂。css
避免讓這些「瘟疫」在你的標籤中傳播並保持其簡潔和語義化的最佳方式,就是使用更復雜的CSS選擇器,它們能夠定位於指定的元素而不用使用額外的class或id,並且經過這種方式也可讓咱們的代碼和樣式更加靈活。前端
在深刻研究高級CSS選擇器領域以前,理解CSS優先級是如何工做的是很重要的,這樣咱們就知道如何適當的使用咱們的選擇器並避免浪費大量的時間來調試一些只要咱們注意到優先級的話就很容易被搞定的問題瀏覽器
當咱們寫CSS的時候咱們必須注意有些選擇器在級聯(cascade)上會高於其它選擇器,咱們寫在最後面的選擇器將不必定會覆蓋前面咱們寫在同一個元素的樣式。ide
那麼你如何計算指定選擇器的優先級?若是你考慮到將優先級表示爲用逗號隔開的四個數字就會至關簡單,好比:1, 1, 1, 1 或0, 2, 0, 1工具
讓咱們看幾個例子,這樣或許比較容易理解些:佈局
在下面的例子中,第一個將會起做用,由於它比第二個優先級高:post
至少基本理解優先級是如何工做的是很重要的,可是一些工具好比Firebug,在咱們審查指定元素的時候,按照選擇器的優先級列出全部的css選擇器對讓咱們知道在指定元素上哪一個選擇器是有效的是頗有用的。測試
讓你很是容易的看到那個選擇器做用於一個元素上了。字體
有用的文章:網站
屬性選擇器(Attribute selector)讓你能夠基於屬性來定位一個元素。你能夠只指定該元素的某個屬性,這樣全部使用該屬性——而無論它的值——的這個元素都將被定位,也能夠更加明確並定位在這些屬性上使用特定值的元素 —— 這就是屬性選擇器展現它們的威力的地方。
有6個不一樣類型的屬性選擇器:
好比,若是你想要改變你的博客上的日誌部分元素的背景顏色,你可使用一個指定每個class屬性值以「post-」開始的div的屬性選擇器:
div[class|="post"] { background-color: #333; }
該語句將匹配全部class屬性包含」post」並帶」-」字符的div元素。(注:此處英文原文有些上下文不對應,我已經更正——譯者,神飛)
屬性選擇器的另外一個頗有用的用處是定位不一樣類型的input元素。好比,若是你想讓你的文本輸入框使用一個特定的寬度,你可使用下面的屬性選擇器:
input[type="text"] { width: 200px; }
這將匹配全部type屬性值等於「text」的input元素。
如今咱們可能像爲網站上不一樣的文件類型的連接添加不一樣的圖標,這樣你的網站的訪客就會知道他們將得到一個圖片、或者PDF文件、或者是一個word文檔等。這就可使用屬性選擇器來實現:
a[href*=".jpg"] { background: url(jpeg.gif) no-repeat left 50%; padding: 2px 0 2px 20px; } a[href*=".pdf"] { background: url(pdf.gif) no-repeat left 50%; padding: 2px 0 2px 20px; } a[href*=".doc"] { background: url(word.gif) no-repeat left 50%; padding: 2px 0 2px 20px; }
在此例中,咱們使用了一個定位全部的連接(a)的href屬性分別以.jpg,.pdf或.doc結束(*)的屬性選擇器。詳細可查看前端觀察以前的一篇文章《使用CSS選擇器建立個性化連接樣式》
除了Internet Explorer 6,全部的主流瀏覽器都支持屬性選擇器。這意味着,若是你在你的網站上使用了屬性選擇器,你應該確保IE6用戶將仍能得到一個可用的網站。好比咱們的第三個例子,爲連接添加圖標能夠給你的網站帶來另外一個級別的可用性,可是若是這些連接不顯示任何圖標,該網站仍然仍是可用的。
子選擇器用符號「>」表示。它容許你定位某個元素的第一級子元素。
好比,若是你想匹配全部的做爲你的網站側欄的div的子元素的h2元素,而不是多是在div元素內的全部h2元素,也不是div的孫元素(或者更低級別的),你就可使用下面的選擇器:
div#sidebar > h2 { font-size: 20px; }
你固然也能夠同時使用子元素和後代元素。好比,若是你想定位只有在body元素的子級div元素內的blockquote元素(好比你想匹配主要的div內的blockquotes,而不是其它部分的:
body > div > div blockquote { margin-left: 30px; }
和屬性選擇器同樣,子選擇器不被IE6支持。若是你經過這種方式要實現的效果和網站的可用性或整體設計息息相關,你能夠考慮使用一個class,或者使用只針對IE6的樣式,可是這將有悖使用子選擇器的目的。
有兩類兄弟組合:臨近兄弟組合和普通兄弟組合
該選擇器使用加號「+」來連接先後兩個選擇器。選擇器中的元素有同一個父親,並且第二個必須牢牢的跟着第一個。
臨近兄弟組合能夠灰常有用,好比,在處理文字的時候。好比咱們想對段落後面的h2標題添加一個頂間距「margin-top」(固然或許你無需爲h1標籤後面的h2添加,或者它多是頁面的第一個元素):
p + h2 { margin-top: 10px; }
你甚至能夠更加具體,你想定位某個特定的div後面的h2:
div.post p + h2 { margin-top: 10px; }
或者你能夠搞得更加複雜:頁面的第一個段落的第一行字母顯示爲小寫字母。
.post h1 + p:first-line { font-variant: small-caps; }
由於可能大部分日誌/文章的第一個段落都會牢牢的在H1標籤的後面。你能夠在你的選擇器中藉助於h1標籤。
普通兄弟組合和臨近兄弟組合的工做原理很像,不一樣的是第二個選擇其無需牢牢跟隨第一個。
若是你須要定位全部的某個特定的div裏面而且跟在h1標籤後面的p標籤的話(你可能想要這些p標籤比擬的日誌的標題前面的文字大些),你就可使用這個選擇器:
.post h1 ~ p { font-size: 13px; }
注:這兩個選擇器太像了,全部不是很好理解,能夠試一試下面的這個例子:
CSS:
p + h2{color:red; } p ~ h2{font-weight:700; }
HTML:
<p>咳咳,內容。</p> <h2>標題1</h2> <h2>標題2</h2>
看看第二個h2的顏色就能夠理解了吧?臨近兄弟組合只能匹配第一個選擇器後面的第一個兄弟選擇其,普通兄弟組合則能匹配全部。注:該部分英文原文沒有,是神飛翻譯時本身添加。
Internet Explorer 6依然不能理解兄弟選擇器,可是,另外一種狀況,若是你的用戶中只有一小部分是IE6用戶,並且網站的結構不會被破壞或者受到嚴重影響,這是實現不少很酷的效果而無需在你的HTML代碼中添加無用的class或id。
之因此被稱爲動態僞類是由於它們並不存在於HTML中——而是隻有當用戶和網站交互的時候纔會呈現。
有兩類動態僞類:連接 和用戶行爲。連接就是:link 和:visited,而用戶行爲包括:hover、:active 和:focus。
在本文中提到的css選擇器中,這幾個應該是最經常使用到的。
:link僞類用於連接還沒有被用戶訪問的時候,而:visited 僞類用於用戶訪問過的連接,也就是說它們是相反的。
:hover僞類用於用戶移動他們的鼠標在元素上,而還沒有觸發或點擊它的時候。:active僞類應用於用戶點擊元素的狀況。最後,:focus僞類用於元素成爲焦點的時候——最經常使用於表單元素。
你能夠在你的樣式表中使用多種用戶行爲動態僞類,這樣你就能夠,好比,根據用戶的鼠標只是滑過或懸停的時候,爲一個輸入框定義不一樣的背景色:
input:focus { background: #D2D2D2; border: 1px solid #5E5E5E; } input:focus:hover { background: #C7C7C7; }
瀏覽器兼容性
動態僞類被全部的現代瀏覽器支持,甚至IE6,可是請注意,對於IE系列瀏覽器來講,IE6只容許:hover 僞類應用於連接元素(a標籤)並且只有IE8接受:active狀態。
:first-child僞類容許你定位某個元素第一個子元素。好比,若是你想給你的無須列表的第一個li添加一個margin-top,你就能夠這樣寫:
ul > li:first-child { margin-top: 10px; }
讓咱們來看一看另外一個例子:好比你想讓你的博客的側欄的H2標籤都有個頂部邊距,以將標題和它們前面的內容區分開來,可是第一個h2不須要,你就可使用下面的代碼:
#sidebar > h2 { margin-top: 10px; } #sidebar > h2:first-child { margin-top: 0; }
瀏覽器兼容性
IE6 不支持 :first-child 僞類。根據僞類應用到的設計的不一樣,它或許不會成爲關注的主要問題。好比,若是你使用:first-child 選擇器來移除標題或段落上的頭部或底部的間距,你的佈局在IE6中不會壞掉,它只會看起來有些不一樣。可是若是你使用:first-child選擇器從一個,好比浮動元素,移除左邊距或右邊距,將會讓你的設計亂掉。
語言僞類:lang(),容許你匹配一個基於它的語言的元素。
你如,你想讓你的網站的某個特定的連接根據頁面的語言有不一樣的背景顏色:
:lang(en) > a#flag { background-image: url(english.gif); } :lang(fr) > a#flag { background-image: url(french.gif); }
這個選擇器將會匹配相關的連接——若是頁面的語言等於「en」或「fr」,或者以「en」或「fr」開頭並在後面帶個連字符「-」的話。
瀏覽器兼容性
不幸的是,只有IE瀏覽器中只有IE8支持該選擇器,其它的主要瀏覽器都支持該僞類選擇器。
當你使用錨點(片斷標識符 fragment identifier)的時候,好比,http://www.smashingmagazine.com/2009/08/02/bauhaus-ninety-years-of-inspiration/#comments,這「#comments」就是一個片斷標識符,你就可使用:target僞類來控制目標的樣式。
舉個例子,好比你有一個很長的使用了不少文字和h2標題的頁面,而後在頁面的頭部有一個對這些標題的索引。若是在點擊索引內的某個連接時,相應的標題以某種方式高亮,而後滾動到相應的位置,對讀者就會頗有用。很簡單。
h2:target { background: #F2EBD6; }
瀏覽器兼容性
這一次,IE瀏覽器徹底不支持:target僞類,另外一個小問題就是Opera 在使用「前進」和後退按鈕時不支持該選擇器。可是其它的各個主流瀏覽器都支持該選擇器。
有些HTML元素有enable 或disabled 狀態(好比,文本輸入框)和 checked 或unchecked 狀態(單選按鈕和複選框)。這些狀態就可使用:enabled、:disabled 或:checked 僞類來分別定位。
那麼你就會想,若是任意一個禁用的(disabled)文本框應該使用淺灰色的背景和虛線邊框:
input:disabled { border:1px dotted #999; background:#F2F2F2; }
你也可能會想讓全部選中的複選框有個左邊距(這樣就能夠在衆多的複選框中很容易認出來):
input[type=」checkbox」]:checked { margin-left: 15px; }
瀏覽器兼容性
全部的主流瀏覽器,除了咱們經常不報但願的IE系列瀏覽器,都支持UI元素狀態僞類。若是你考慮只是添加附加級別的細節和加強網站的可用性,這個仍然是能夠採用的。
:nth-child()僞類容許你定位某個父級元素的一個或多個特定的子元素.
你能夠經過定義它的值爲一個整數來定位某個單個子元素:
ul li:nth-child(3) { color: red; }
這將會讓ul元素的第三個li元素的文字變成紅色。注意若是在ul裏面有個其它類型的元素(不是li),它也會算做其子元素。
你可使用表達式來定位子元素。好比,下面的表達式將從第四個開始匹配每第三個元素。
ul li:nth-child(3n+4) { color: yellow; }
在上面的這個例子中,第一個黃色的li元素將會是第四個。若是也想從第一個開始匹配,你可使用一個簡單的表達式:
ul li:nth-child(3n) { color: yellow; }
這樣的話,第一個黃色的li元素將會是第三個子元素,而後是它後面的每隔第三個。如今想象一下若是你只想匹配列表中的前四個子元素:
ul li:nth-child(-n+4) { color: green; }
:nth-child的值一樣也能夠被定義爲「even」 或「odd」,和「2n」 (第偶數個) 或「2n+1」 (第奇數個)的效果是同樣的。
:nth-last-child僞類基本上和:nth-child僞類的做用相同,可是它從最後一個元素開始算。
使用上面的一個例子來看看:
ul li:nth-child(-n+4) { color: green; }
不是匹配最前面的四個li元素,該選擇器匹配最後面的四個元素。
你一樣可使用「even」 或「odd」只,一樣與nth-child不一樣的是,這是從最後面的元素開始算的:
ul li:nth-last-child(odd) { color: grey; }
:nth-of-type僞類和:nth-child也很像,不一樣的是它只計算選擇器中指定的那個元素。
這對定位元素中包含大量不一樣的元素的狀況會頗有用。好比,咱們想控制一個文本塊中的每隔一個段落,可是咱們又想要無視其它元素好比圖片和引用塊:
p:nth-of-type(even) { color: blue; }
你也可使用一些值,就像在:nth-child中使用的同樣。
你能猜到它吧?!:nth-last-of-type 僞類能夠像前面提到的:nth-last-child同樣使用,可是此次,它將之匹配你在選擇器中指定的元素類型:
ul li:nth-last-of-type(-n+4) { color: green; }
咱們能夠更加的聰明一些,在一個大的塊級選擇器中結合多種這樣的僞類。好比咱們想讓文章中的全部的圖片左浮動,除了第一個和最後一個(咱們能夠假設他們是滿寬的,無須浮動):
.post img:nth-of-type(n+2):nth-last-of-type(n+2) { float: left; }
因此在這個選擇器的第一部分,咱們從第二個圖片開始定位每個圖片。在第二部分中,咱們定位全部的圖片,除了最後一個。由於這兩個選擇器並不是互斥的,咱們能夠同時使用它們,這樣就能夠一會兒排除第一個和最後一個元素!
:last-child僞類的做用相似於:first-child 僞類,可是會定位父級元素的最後一個子元素。
讓咱們假設你不想讓你的日誌的div的最後一個段落也有一個底部邊距:
.post > p:last-child { margin-bottom: 0; }
該選擇器將定位class爲」post」的元素的最後一個直接子級段落。
:first-of-type 僞類用於定位一個父級元素下的第一個同類子元素。
好比,你能夠定位某個特定的div的第一個子級段落(p),並讓其第一行字母大寫:
.post > p:first-of-type:first-line { font-variant: small-caps; }
在這個選擇器中,你能夠肯定你是在只定位class爲」post」的元素的直接子級p元素,並且仍是匹配第一個子級p元素。
:last-of-type僞類與此相似,只是匹配最後一個子元素。
o nly-child僞類表示一個元素是它的父級元素的惟一一個子元素。
好比說,你有一些盒子(「news」),裏面有一些文字段落,當你有多於一個段落的時候,你想讓文字比只有一個段落的時候小一些:
div.news > p { font-size: 1.2em; } div.news > p:only-child { font-size: 1.5em; }
第一個選擇器中,咱們定義」news」div的全部子級p元素的字體大小。在第二個中,咱們覆蓋以前的字體大小,若是該p元素是「news」 div的惟一子元素的時候,它的字體大小會比較大一些。
only-of-type僞類表示一個元素是它的父級元素的惟一一個相同類型的子元素。
這有用什麼用?假設你有一些日誌,每一篇都有個class爲」post」的div,他們中的一些有多於一張圖片,可是有些可能就只有一張圖片。你想讓後者中的圖片水平居中,而在其它的有多於一張圖片的日誌中,就將它左浮動。這個需求用這個選擇器就很容易實現:
.post > img { float: left; } .post > img:only-of-type { float: none; margin: auto; }
:empty僞類表示一個元素裏面沒有任何內容。
這個選擇器能夠用不少種用途。好比,你在你的「sidebar」中有若干個盒子,可是不想讓空盒子顯示出來:
#sidebar .box:empty { display: none; }
注意,就算」box」div裏面只有一個空格,它也不會被css看成空標籤的,這樣就不能匹配該選擇器了。
Internet Explorer (直到8.0版本)都不支持結構僞類。Firefox、Safari 和Opera 在其最新版本的瀏覽器中指出這些選擇器。這意味着,使用這些選擇器對網站的可用性和可訪問性是頗有用的,或者若是網站的用戶中的大部分是使用IE並且你不想在某些細節上無視他們,最好仍是保持使用通用的class和簡單的選擇器來迎合這些選擇器。不然你會被搞瘋的!
否認選擇器:not(),可讓你定位不匹配該選擇器的元素
好比,若是你須要定義表單元素中的input元素,可是又不想包括submit類型的input的時候會灰常有用——你想它們有不一樣的樣式,以看起來像按鈕:
input:not([type="submit"]) { width: 200px; padding: 3px; border: 1px solid #000000; }
另外一個例子,你想你的日誌的div中的全部段落(p)有比較大的字體,除了表示時間和日期的段落:
.post p:not(.date) { font-size: 13px; }
你能夠想象這個選擇器能帶給你的潛力了吧,你可以從你的CSS文件中剝離(剔除)的無用的大量選擇器也被它普遍支持嗎?
Internet Explorer在這裏經常是讓咱們感到掃興的東西:一點都不支持,甚至在IE8中。這大概意味着這些選擇器將仍不得不等到一些開發者開始再也不顧慮將它添加到他們的樣式表中才會普及。
僞元素容許你操做HTML中不是真實存在的元素,好比一個文本塊的第一行或者第一個字母。
僞元素在CSS 2.1中就已經存在,可是CSS 3說明書表示他們應該使用雙冒號「::」,以與僞類區分開來。在CSS 2.1中,他們也是使用單個冒號「:」的。瀏覽器會將可以接受兩種格式,除非這些僞元素只存在於CSS3中。
::first-line僞元素將匹配block、inline-block、table-caption、table-cell等等級別元素的第一行
這對在你的文字塊上添加一些微妙的排版細節至關有用,好比,將一片文章的第一行文字改爲小寫字母:
h1 + p::first-line { font-variant: small-caps; }
若是你專心的閱讀了咱們前面的內容,你將會了解到上面的語法意味着,牢牢的跟在H1標籤以後(+)的段落會將其第一行文字顯示爲小寫字母。
你也能夠針對相關的div的第一行,而不用針對實際的段落標籤(p):
div.post p::first-line { font-variant: small-caps; }
或者更進一步,定位某個特低的div的第一個段落的第一行:
div.post > p:first-child::first-line { font-variant: small-caps; }
這裏,「>」符號表示你指定的是post div的直接子級元素,這樣若是段落被包括在第二級div中,它就不會匹配這個選擇器。
::first-letter僞元素將會匹配一個文本塊的第一個字母,除非在同一行裏面包含一些其它元素,好比圖片。
和::first-line僞類同樣,::first-letter一般用於給文本元素添加排版細節,好比下沉字母或首字母。
這裏是如何使用::first-letter僞元素建立首字下沉的例子:
p { font-size: 12px; } p::first-letter { font-size: 24px; float: left; }
注意若是你在某些元素中同時使用::first-line 和::first-letter ,::first-letter 屬性將覆蓋從::first-line中繼承下來的某些屬性。
若是你不知道W3C規則的話,這個元素有時會產生意想不到的結果:它事實上是使用最長的規則的選擇器!因此若是你計劃使用它的話最好仔細的閱讀一下 (其它選擇器也同樣)。
::before和::after 僞元素用於在一個元素的前面或後面插入內容,純CSS方法。
這些元素將繼承它們將附加的元素的大部分屬性。
假設你想在你的頁面中的圖標的描述前面添加文字「Graphic number x:」。你將無需寫文字「Graphic number」,或者本身手動添加數字:
.post { counter-reset: image; } p.description::before { content: "Figure number " counter(image) ": "; counter-increment: image; }
那麼這會產生什麼?
首先,咱們告訴HTML來建立「image」計數器。好比咱們能夠添加該屬性到頁面的body。一樣咱們也能夠給該計數器起任何一個名字,只要你想,只要咱們經常使用一樣的名字引用它:本身試試吧!
那麼咱們想在class爲」description」的每個段落以前添加這一塊內容: 「Figure number 」 — 注意只有咱們在引號裏面寫的內容纔會被建立到頁面中,因此咱們也要添加一個空格!
而後,咱們就有了counter(image):這將用到咱們以前在.post選擇器中定義的屬性。它默認會從數字1開始。
下一個屬性在那裏表示計數器知道對於每個p.description,它須要將image計數器增長1 (counter-increment: image)。
它並不像看起來的那麼複雜,並且還會灰常的有用。
::before和::after僞元素經常只使用content屬性,來添加一些短語或排版元素,可是這裏咱們展現了咱們若是以一種更增強大的結合counter-reset和counter-increment屬性的方式來使用它們。
有趣的是: ::first-line 和::first-letter 僞元素能夠匹配使用::before僞元素生成的內容,若是存在的話。
若是使用單個冒號的話(好比, :first-letter, 而不是::first-letter),這些僞元素被IE8支持(可是不被IE7或6支持)。可是左右其餘的主流瀏覽器都支持這些選擇器。
乏味的講述終於結束了,如今該你來領悟本文的要義並本身嘗試了: 開始經過建立實驗性的頁面並測試全部的這些選擇器,在有疑問的時候返回這裏並確保老是遵循W3C的規則,可是請不要只是坐在那裏想這些選擇器還沒有被徹底支持你就無視它們。
若是你勇於冒險,或者你不懼怕放棄以前的遍地無用和非語義化的class和id,爲何不嘗試一兩個這些強大的CSS選擇器到你的下一個項目中呢?咱們保證你不會回頭的!