前端er們大都或多或少地接觸過CSS僞類和僞元素,好比最多見的:focus
,:hover
以及<a>
標籤的:link
、visited
等,僞元素較常見的好比:before
、:after
等。css
其實上面提到的這些僞類和僞元素都是CSS1和CSS2中的概念,CSS1和CSS2中對僞類的僞元素的區別比較模糊,甚至常常有同行將:before
、:after
稱爲僞類。CSS3對這兩個概念作了相對較清晰地概念,而且在語法上也很明顯的講兩者區別開。html
首先看看CSS2中對僞類的定義:前端
單單看定義徹底不懂在講什麼。截止CSS2,僞類有如下幾種(偷個懶,截圖引自W3School):express
而後是CSS3對僞類的定義:app
The pseudo-class concept is introduced to permit selection based on information that lies outside of the document tree or that cannot be expressed using the other simple selectors.ide
A pseudo-class always consists of a "colon" (:) followed by the name of the pseudo-class and optionally by a value between parentheses.字體
Pseudo-classes are allowed in all sequences of simple selectors contained in a selector. Pseudo-classes are allowed anywhere in sequences of simple selectors, after the leading type selector or universal selector (possibly omitted). Pseudo-class names are case-insensitive. Some pseudo-classes are mutually exclusive, while others can be applied simultaneously to the same element. Pseudo-classes may be dynamic, in the sense that an element may acquire or lose a pseudo-class while a user interacts with the document.ui
簡單翻譯一下:this
僞類存在的意義是爲了經過選擇器找到那些不存在與DOM樹中的信息以及不能被常規CSS選擇器獲取到的信息。
僞類由一個冒號
:
開頭,冒號後面是僞類的名稱和包含在圓括號中的可選參數。
任何常規選擇器能夠再任何位置使用僞類。僞類語法不區別大小寫。一些僞類的做用會互斥,另一些僞類能夠同時被同一個元素使用。而且,爲了知足用戶在操做DOM時產生的DOM結構改變,僞類也能夠是動態的。
其實第一段話就囊括CSS3僞類的所有定義了,這段話中指出CSS3僞類的功能有兩種:
<a>
標籤的:link
、visited
等,這些信息不存在與DOM樹結構中,只能經過CSS選擇器來獲取;:target
,它的做用是匹配文檔(頁面)的URI中某個標誌符的目標元素,例如咱們能夠經過以下代碼來實現頁面內的區域跳轉:<ul class="tabs"> <li><a href="#tab1">標籤一</a></li> <li><a href="#tab2">標籤二</a></li> <li><a href="#tab3">標籤三</a></li> </ul> <div id="tab1" class="tab_content"> <!--tabed content--></div> <div id="tab2" class="tab_content"> <!--tabed content--></div> <div id="tab3" class="tab_content"> <!--tabed content--></div>
CSS代碼以下:
.tab_content { height: 800px; background: red; margin-bottom: 100px; } #tab1:target, #tab2:target, #tab3:target { background:blue; }
固然,經過JavaScript來獲取window.location.hash
一樣能夠實現上例中的效果,但這是另一回事了。總之,:target
經過CSS實現了常規CSS沒法實現的邏輯。
其實對比來看,CSS2中對僞類的定義也是合理地,可是它並未指出「某些選擇器」是「哪些選擇器」,CSS3對僞類的定義就顯得明確了不少。
再舉個栗子,經過: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
。
若是不使用僞類而是使用JavaScript代碼來實現上述的效果,恐怕要複雜不少。
能夠總結出:nth-child()
僞類的效果是將被常規css選擇器篩選出的元素按照既定規定進行再次篩選。
CSS3中還引入了許多新的僞類,感興趣的讀者能夠參考這裏。
CSS2中對僞元素的定義:
好吧,跟僞類的定義徹底同樣有木有(吐槽一下W3School的翻譯)。其實人家這樣翻譯也沒有錯,原本CSS2對僞類和僞元素的定義就是徹底同樣的:
CSS introduces the concepts of pseudo-elements and pseudo-classes to permit formatting based on information that lies outside the document tree.
截止CSS2,僞元素有如下幾種:
而後再看CSS3中僞元素的定義:
Pseudo-elements create abstractions about the document tree beyond those specified by the document language. For instance, document languages do not offer mechanisms to access the first letter or first line of an element's content. Pseudo-elements allow authors to refer to this otherwise inaccessible information. Pseudo-elements may also provide authors a way to refer to content that does not exist in the source document (e.g., the ::before and ::after pseudo-elements give access to generated content).
A pseudo-element is made of two colons (::) followed by the name of the pseudo-element.
This :: notation is introduced by the current document in order to establish a discrimination between pseudo-classes and pseudo-elements. For compatibility with existing style sheets, user agents must also accept the previous one-colon notation for pseudo-elements introduced in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and :after). This compatibility is not allowed for the new pseudo-elements introduced in this specification.
Only one pseudo-element may appear per selector, and if present it must appear after the sequence of simple selectors that represents the subjects of the selector.
Note: A future version of this specification may allow multiple pseudo-elements per selector.
簡單翻譯一下:
僞元素在DOM樹中建立了一些抽象元素,這些抽象元素是不存在於文檔語言裏的(能夠理解爲html源碼)。好比:documen接口不提供訪問元素內容的第一個字或者第一行的機制,而僞元素能夠使開發者能夠提取到這些信息。而且,一些僞元素能夠使開發者獲取到不存在於源文檔中的內容(好比常見的
::before
,::after
)。
僞元素的由兩個冒號
::
開頭,而後是僞元素的名稱。
使用兩個冒號
::
是爲了區別僞類和僞元素(CSS2中並無區別)。固然,考慮到兼容性,CSS2中已存的僞元素仍然能夠使用一個冒號:
的語法,可是CSS3中新增的僞元素必須使用兩個冒號::
。
一個選擇器只能使用一個僞元素,而且僞元素必須處於選擇器語句的最後。
注:不排除將來會加入同時使用多個僞元素的機制。
一樣,第一段話是僞元素的清晰定義,也是僞元素與僞類最大的區別。簡單來講,僞元素建立了一個虛擬容器,這個容器不包含任何DOM元素,可是能夠包含內容。另外,開發者還能夠爲僞元素定製樣式。
已::first-line
爲例,它獲取了指定元素的第一行內容而且將第一行的內容加入到虛擬容器中。若是經過JavaScript來實現這個邏輯,那麼要考慮的因素就太多了,好比制定元素的寬度、字體大小,甚至浮動元素的圖文混排等等。固然,這些問題確實是能夠用JavaScript來解決的,可是相對於::first-line
簡簡單單的幾個字,用JavaScript恐怕不止這些吧!
舉個綜合使用僞類和僞元素的栗子:
q:lang(de)::after{ content: " (German) "; } q:lang(en)::after{ content: " (English) "; } q:lang(fr)::after{ content: " (French) "; } q:not(:lang(fr)):not(:lang(de)):not(:lang(en))::after{ content: " (Unrecognized language) "; }
以上代碼經過僞類"lang
獲取不一樣lang
屬性的節點,併爲之設置僞元素::after
,僞元素的內容是此節點的語言類型。
最後,總結一下僞類與僞元素的特性及其區別: