1. 程式人生 > 實用技巧 >CSS的核心選擇器

CSS的核心選擇器

我們能真切地感覺到,選擇器是CSS的核心部分。如果沒有它們的話,我們除了把屬性嵌入到每個元素裡,就沒有其他辦法能把樣式應用在元素上了,那真是太糟糕了。通過選擇器賦予的選擇任何形式任何種類元素的能力,我們可以只用很少的幾行CSS完成很大一部分樣式設定工作。

本章我們將深入探討如何巧妙地使用選擇器,並且概述一下哪些型別的選擇器被普遍支援且應用最為廣泛。

1 偽類與偽元素

CSS中有兩種“偽”字頭的選擇器:偽類(pseudo-class)和偽元素(pseudo-element)。CSS2.1中的偽類有:

 :link——未訪問過的連結;

 :visited——訪問過的連結;

 :hover——滑鼠懸停的元素;

 :focus——獲取焦點的元素;

 :active——啟用的元素(例如一個被單擊的連結元素);

 :first-child——作為其他元素第一個子元素的元素;

 :lang()——根據元素的lang屬性確定的元素。

CSS2.1中的偽元素有:

 ::first-line

 ::first-letter

 ::before

 ::after

那麼區別在哪兒呢?區別就在於這些偽選擇器影響文件的方式不同。偽類的表現有點兒像給文件新增類,而偽元素的效果就好像有元素被插入到了文件中。

::first-letter為例,假設你要把每個h1的第一個字母增大到其他字母的兩倍半(如圖

2-1

所示),很簡單:

h1::first-letter {font-size: 250%;}

這就彷彿CSS和標記被修改成了這樣:

h1 first-letter {font-size: 250%;}

<h1><first-letter>H</first-letter>owdy, y’all!</h1>


2-1 放大h1的第一個字母

這真的是瀏覽器內部真實發生的情況嗎?誰知道呢,反正結果確實像是發生了這種情況,因此才有了“偽元素”這個名字。

類似地,偽類的表現就像是它們使文件中的元素被添加了新的類。例如,想象一下若對於每一個作為其他元素第一個子元素的元素,瀏覽器給它們都附加了一個名為

first-child的類,然後就可以像下面這樣為它們應用樣式了:

li.first-child {border-left: none;}

只需要簡單地把點改成冒號就變成了li:first-child,就可以得到同樣的最終效果,而不用費力把類新增到所有標記上。

有時還會看到偽元素使用雙冒號的語法,這是在CSS2.1之後引入的。截至撰寫本書之時,還沒有哪個瀏覽器要求你必須在偽元素前面使用雙冒號的,一個冒號就可以了。

另外提醒讀者,CSS3增加了如下一些偽類,截至撰寫本書之時,它們中的大部分還沒有被廣泛地支援:

 :target

 :root

 :nth-child()

 :nth-of-type()

 :nth-last-of-type()

 :first-of-type

 :last-of-type

 :only-of-type

 :only-child

 :last-child

 :empty

 :not()

 :enabled

 :disabled

 :checked

2 為目標元素新增樣式

當希望指向文件中的某個片段時,目標(target)會非常有用。什麼,怎麼實現?其實非常簡單:

<a href="http://example.com/law.html#sec2-7">Section 2.7</a>

任何人單擊這個連結(如果瀏覽器處理正確的話)將不止跳轉到目標頁,而且還會跳到頁面中文件片段識別符號(地址中的#sec2-7部分)出現的地方。這有時是通過錨點(anchor)實現的,但是隻用ID來實現會更好一些。例如有如下兩種場景:

<h3><a name="sec2-7">Exceptions</a></h3>

<h3 id="sec2-7">Exceptions</h3>

這兩種情況下,當瀏覽器跳到了文件中的目標位置時,都不會有任何視覺提示告知你已經到達了目標位置,而使用:target偽類就可以給出視覺提示。例如,若想讓作為某個文件片段識別符號目標的h3擁有特定的提示效果(如圖2-2所示),可以這樣寫:

h3:target {color: maroon;

background: #FFA;}


2-2 突出顯示目標元素(另見彩插圖2-2

當然,你或許想把這個樣式應用到任何目標元素上,而不管它是什麼元素,那麼只需要把h3換成一個通用選擇器即可,就像這樣:

*:target {color: maroon;

background: #FFA;}

從技術上講,這種情況下通用選擇器也是可選的,可以把這個選擇器簡單地寫成:target

如果想讓目標樣式多一點Web 2.0的感覺,還可以設定一個漸隱背景的效果。你懂的,就是那種“你已經完成了某項操作,所以頁面上的一塊背景會從×××變到白色,讓你知道已經完成了該項操作”的效果。通過:target和一個動畫GIF可以很容易地實現這種效果,只需要建立一個從×××漸變到白色(如果白色是你網站的背景色的話)的動畫並且把它當做背景影象。

*:target {background: url(/pix/yellow-fade.gif);}

3 特殊性

你很難快速地把特殊性(specificity)這個詞讀3遍,而若想徹底地掌握它甚至更難。但是,它卻是理解CSS規則之間相互作用的關鍵。

特殊性是一個選擇器“特殊程度”的數字表示,有3樣東西經常被用來確定選擇器的特殊性:

每個元素描述符貢獻0,0,0,1

每個類、偽類或者屬性描述符貢獻0,0,1,0

每個ID描述符貢獻0,1,0,0

先不要抓狂,來看幾個小例子。

div ul ul li 0,0,0,4 4個元素描述符

div.aside ul li 0,0,1,3 1個類描述符,3個元素描述符

a:hover 0,0,1,1 1個偽類描述符,1個元素描述符

div.navlinks a:hover 0,0,2,2 1個偽類描述符,1個類描述符,2個元素描述符

#title em 0,1,0,1 1ID描述符,1個元素描述符

h1#title em 0,1,0,2 1ID描述符,2個元素描述符

希望這些能夠幫助你理解特殊性是如何計算的。那麼,為什麼是逗號呢?因為可以這麼說,每個“級別”的特殊性的值都是相互獨立的。因此,具有一個單獨的類描述符的選擇器會比由13個元素描述符組成的選擇器擁有更高的特殊性。

.aside /* 0,0,1,0 */

div table tbody tr td div ul li ol li ul li pre /* 0,0,0,13 */

第一個選擇器左數第三位的“1”勝過了第二個選擇器同樣位置的“0”,基於這樣的事實,第二個選擇器第四位的“13”(在這個非常有限的例子中)就毫無意義了。逗號可以使我們看得更清楚,否則選擇器的特殊性可能被寫成“10”和“13”,從而造成後者特殊性更高的假象(在CSS的早期還沒有引入逗號分隔符時,這是經常出現的誤解)。

還有另外一種常見的誤解,就是特殊性的結構相近問題。例如,假設有如下兩個選擇器:

ul li {font-style: normal;}

html li {font-style: italic;}

它們當中哪個會贏呢?它們都有兩個元素描述符,這意味著它們的特殊性都是0,0,0,2。其實,後寫的會贏,與html元素相比ul元素在文件中的位置離li元素更近也不管用。特殊性只是單純的數值,它不會以任何方式評估頁面的結構。結果,列表元素將全部變成斜體,因為當特殊性相等時後宣告的規則會勝出。

因為我說過有3樣東西影響特殊性,所以你或許想知道特殊性識別符號第一位的0是幹嘛用的。其實,第一個0是用於行內樣式(inline style)的,且僅用於行內樣式。因此,如果有下面這樣的樣式和標記,則div的背景將會是藍色。

div#header {background: purple;} /* 0,1,0,0 */

<div id="header" style="background: blue;"> <!-- 1,0,0,0 -->

——摘自《精彩絕倫的CSS》

轉載於:https://blog.51cto.com/turingbook/898174