前端er們大都或多或少地接觸過CSS偽類和偽元素,比如最常見的:focus、:hover以及<a>標簽的:link、:visited等,偽元素較常見的比如:before、:after等。
在這里也許有不少人都見過:before,::before這樣的寫法,估計有些人很納悶,這兩者有什么區別嗎?
有疑問,那我們就先把疑問解決了先,不要把疑問留着。其實:before,::before這兩種寫法都是等效,只是:befor是CSS2的寫法,::before是CSS3的寫法。雙冒號(::)這是CSS3 規范中的要求,目的是為了區分偽類和偽元素,大多數瀏覽器都支持這兩種表示方式。單冒號(:)用於 CSS3 偽類,雙冒號(::)用於 CSS3 偽元素。對於 CSS2 中已經有的偽元素,例如 :before,單冒號和雙冒號的寫法 ::before 作用是一樣的。一般情況下為兼容性考慮使用單冒號(:)。
解決完疑問,那我們就可以愉快的開始接下來的內容了。
偽類 - pseudo classes
偽類存在的意義是為了通過選擇器找到那些不存在與DOM樹中的信息(例如<a>標簽的:link、:visited等,這些信息不存在與DOM樹結構中,只能通過CSS選擇器來獲取)以及不能被常規CSS選擇器獲取到的信息(例如要修改第幾個子元素的樣式)。
偽類的語法:
selector : pseudo-class {property: value}
CSS 類也可與偽類搭配使用:
selector.class : pseudo-class {property: value}
偽類選擇器(這里的偽類選擇器等效於文中所涉及到的偽類)與我們常用的類選擇器的區別是:類選擇器可以隨便起名,譬如“p.right”,然后在頁面p標簽的class類中加入類“right”,但是偽類選擇器是CSS中已經定義好的選擇器,不能隨便起名。下面是一些我們常見的偽類選擇器:
:active —— 樣式添加到正在被激活的元素
:focus —— 樣式添加到獲得焦點的元素
:hover —— 樣式添加到鼠標懸浮的元素
:link —— 樣式添加到未被訪問過的鏈接
:visited —— 樣式添加到已經訪問過的鏈接
:first-child —— 樣式添加到第一個子元素
:lang —— 樣式添加到指定lang語言的標簽
如何理解偽類可以通過選擇器找到那些不存在與DOM樹中的信息,我們看看下面這個栗子:
a:link {color: #FF0000} /* 未訪問的鏈接 */ a:visited {color: #00FF00} /* 已訪問的鏈接 */ a:hover {color: #FF00FF} /* 鼠標移動到鏈接上 */ a:active {color: #0000FF} /* 選定的鏈接 */
鏈接的不同狀態都可以不同的方式顯示,這些狀態包括:活動狀態,已被訪問狀態,未被訪問狀態,和鼠標懸停狀態。顯然這個些狀態並沒有存在DOM樹的信息里面。
我們再來看個栗子:
p:first-child { color: red; }
<div> <p>我是文本</p> <p>我是文本</p> </div>
這個效果相當於下面的常規寫法:
.red{ color: red; }
<div> <p class="red">我是文本</p> <p>我是文本</p> </div>
再舉個栗子,通過:nth-child()偽類可以實現一些很有意思的效果,比如:
table tr:nth-child(2n) td{ background-color: #ccc; } table tr:nth-child(2n+1) td{ background-color: #fff; } table tr:nth-child(2n+1):nth-child(5n) td{ background-color: #f0f; }
上面的代碼將所有偶數行背景色設置為#ccc,不能被5整除的奇數行設置背景色#fff,能夠被5整除的奇數行設置背景色#f0f。這如果要用常規CSS去實習這效果,恐怕沒法搞吧,因為常規CSS選擇器並沒辦法獲取到這些元素的位置信息。
CSS3中還引入了許多新的偽類,感興趣的可以參考這里。
偽元素 - Pseudo-elements
偽元素的語法:
selector:pseudo-element {property:value;}
CSS 類也可以與偽元素配合使用:
selector.class:pseudo-element {property:value;}
偽元素在DOM樹中創建了一些抽象元素,這些抽象元素是不存在於文檔語言里的(可以理解為html源碼)。比如:documen接口不提供訪問元素內容的第一個字或者第一行的機制,而偽元素可以使開發者可以提取到這些信息。並且,一些偽元素可以使開發者獲取到不存在於源文檔中的內容(比如常見的::before,::after)。
上面段話是偽元素的清晰定義,也是偽元素與偽類最大的區別。簡單來說,偽元素創建了一個虛擬容器,這個容器不包含任何DOM元素,但是可以包含內容。另外,開發者還可以為偽元素定制樣式。
常見的偽元素種類:
:first-letter —— 樣式添加到文本首字母
:first-line —— 樣式添加到文本首行
:before —— 樣式添加到元素之前
:after —— 樣式添加到元素之后
偽元素的由兩個冒號::開頭,然后是偽元素的名稱,使用兩個冒號::是為了區別偽類和偽元素(CSS2中並沒有區別)。當然,考慮到兼容性,CSS2中已存的偽元素仍然可以使用一個冒號:的語法,但是CSS3中新增的偽元素必須使用兩個冒號::。
來看個栗子:
p:first-letter { color: red; }
<p>我是文本</p>
其效果相當於:
span { color: red; }
<p><span>我</span>是文本</p>
效果如下:

注意:一個選擇器只能使用一個偽元素,並且偽元素必須處於選擇器語句的最后。
再來看看利用偽元素實現分割線的效果:
.spliter::before, .spliter::after { content: ''; display: inline-block; border-top: 1px solid black; width: 200px; margin: 5px; }
<p class="spliter">分割線</p>
效果如下:

再來看一個:
.test-div { width: 100px; height: 100px; margin-left: 20px; background-color: #eee; } .test-div::before { content: "♥"; color: red; } .test-div::after { content: "♥"; color: blue; }
<div class="test-div">helloworld</div>
效果如圖:

利用偽元素其實還能實現很多效果,比如陰影效果、圖像的形變效果、氣泡效果等等,在這里我就不在貼出來了。師傅領進門,修行在個人,大家感興趣的話百度一下,就有很多。
總結:
-
偽類的效果需要一個實際的類才能達到,而偽元素需要一個實際的元素才能達到。
-
偽類可以同時運用多個,而偽元素只能一次用一個。
-
在CSS3中,偽類用一個冒號:,偽元素用兩個冒號::。
-
為兼容性考慮需要使用一個冒號的格式。
