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的第一個字母
這真的是瀏覽器內部真實發生的情況嗎?誰知道呢,反正結果確實像是發生了這種情況,因此才有了“偽元素”這個名字。
類似地,偽類的表現就像是它們使文件中的元素被添加了新的類。例如,想象一下若對於每一個作為其他元素第一個子元素的元素,瀏覽器給它們都附加了一個名為
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 1個ID描述符,1個元素描述符
h1#title em 0,1,0,2 1個ID描述符,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