CSS偽類與CSS偽元素的區(qū)別及由來具體說明
發(fā)布時(shí)間:2012-12-07 09:44:58 作者:佚名
我要評論

關(guān)于兩者的區(qū)別,其實(shí)是很古老的問題.這里著重寫的是為什么這兩者不同,以及一些平時(shí)容易錯(cuò)過的細(xì)節(jié),需要的朋友可以參考下
關(guān)于兩者的區(qū)別,其實(shí)是很古老的問題。但是時(shí)至今日,由于各種網(wǎng)絡(luò)誤傳以及一些不負(fù)責(zé)任的書籍誤筆,仍然有相當(dāng)多的人將偽類與偽元素混為一談,甚至不乏很多CSS老手。早些年剛?cè)胄械臅r(shí)候,我自己也被深深誤導(dǎo),因?yàn)檎搲锏奶哟蠖嗖魂P(guān)心這種概念的細(xì)微差別,即使有人出來說一句:“這兩個(gè)是不同的”,也只是被更多的帖子淹沒掉而已。所以覺得有必要寫下這些我所知的部分,這里著重寫的是為什么這兩者不同,以及一些平時(shí)容易錯(cuò)過的細(xì)節(jié)。
無論是偽類還是偽元素,都屬于CSS選擇器的范疇。所以它們的定義可以在CSS標(biāo)準(zhǔn)的選擇器章節(jié)找到。分別是 CSS2.1 Selectors 和 CSS Selector Level 3,兩者都已經(jīng)是推薦標(biāo)準(zhǔn)。
標(biāo)準(zhǔn)的定義
在CSS2.1里,5.10 Pseudo-elements and pseudo-classes 描述了這兩個(gè)概念的由來,它們是被一同提及的。但到了 Selector Level 3 里,它們就被分開到兩個(gè)小節(jié)里加以區(qū)分。但無論如何,偽類和偽元素的引入都是因?yàn)樵谖臋n樹里有些信息無法被充分描述,比如CSS沒有“段落的第一行”之類的選擇器,而這在一些出版場景里又是必須的。用標(biāo)準(zhǔn)里的話說:
CSS introduces the concepts of pseudo-elements and pseudo-classes to permit formatting based on information that lies outside the document tree.
簡單翻譯一下,就是:
CSS 引入偽類和偽元素的概念是為了實(shí)現(xiàn)基于文檔樹之外的信息的格式化
這么說很抽象,其實(shí)就是為了描述一些現(xiàn)有CSS無法描述的東西。缺少什么,則引入什么,不管是標(biāo)準(zhǔn),還是人,都是如此成長而來。
偽類與偽元素的區(qū)別
這里我大可以列一個(gè)表格,把所有的偽類和偽元素分開羅列,但這未免太形式化,與其記住“哪些是哪些不是”,不如真正地加以區(qū)分。偽類和偽元素本身就有一個(gè)根本的不同之處,這點(diǎn)直接體現(xiàn)在了標(biāo)準(zhǔn)的描述語句上。
先看一個(gè)偽元素 first-line 例子?,F(xiàn)在有一段HTML,內(nèi)容是一個(gè)段落:
<p>I am the bone of my sword. Steel is my body, and fire is my blood.
I have created over a thoustand blades.
Unknown to Death.Nor known to Life. Have withstood pain to create many weapon.
Yet, those hands will never hold anything. So as I pray, unlimited blade works.</p>
如果我要描述這個(gè)段落的第一行,在不用偽元素的情況下,我會怎么做?想來我一定要嵌套一層 span,然后加上類名:
<p><span class="first-line">I am the bone of my sword. Steel is my body, and fire is my blood. </span>
I have created over a thoustand blades.
Unknown to Death.Nor known to Life. Have withstood pain to create many weapon.
Yet, those hands will never hold anything. So as I pray, unlimited blade works.</p>
再反觀一個(gè)偽類 first-child 的例子,有一個(gè)簡單的列表:
<ul>
<li></li>
<li></li>
</ul>
如果我要描述 ul 的第一個(gè)元素,我無須嵌套新的元素,我只須給第一個(gè)已經(jīng)存在的 li 添加一個(gè)類名就可以了:
<ul>
<li class="first-child"></li>
<li></li>
</ul>
盡管,第一行和第一個(gè)元素,這兩者的語意相似,但最后作用的效果卻完全不同。所以,偽類和偽元素的根本區(qū)別在于:它們是否創(chuàng)造了新的元素(抽象)。從我們模仿其意義的角度來看,如果需要添加新元素加以標(biāo)識的,就是偽元素,反之,如果只需要在既有元素上添加類別的,就是偽類。而這也是為什么,標(biāo)準(zhǔn)精確地使用 “create” 一詞來解釋偽元素,而使用 “classify” 一詞來解釋偽類的原因。一個(gè)描述的是新創(chuàng)建出來的“幽靈”元素,另一個(gè)則是描述已經(jīng)存在的符合“幽靈”類別的元素。
偽類一開始單單只是用來表示一些元素的動態(tài)狀態(tài),典型的就是鏈接的各個(gè)狀態(tài)(LVHA)。隨后CSS2標(biāo)準(zhǔn)擴(kuò)展了其概念范圍,使其成為了所有邏輯上存在但在文檔樹中卻無須標(biāo)識的“幽靈”分類。
偽元素則代表了某個(gè)元素的子元素,這個(gè)子元素雖然在邏輯上存在,但卻并不實(shí)際存在于文檔樹中。
偽類和偽元素混淆的由來
最為混淆的,可能是大部分人都將 :before 和 :after 這樣的偽元素隨口叫做偽類,而且即使在概念混淆的情況下,實(shí)際使用上也毫無問題——因?yàn)榧词垢拍罨煜?,對真正使用也不會造成多少麻?)
CSS Selector Level 3 為了區(qū)分這兩者的混淆,而特意用冒號加以區(qū)分:
偽類用一個(gè)冒號表示 :first-child
偽元素則使用兩個(gè)冒號表示 ::first-line
并且規(guī)定,瀏覽器既要兼容CSS1和2里既存的偽元素的單冒號表示,同時(shí)又要不兼容CSS3新引入的偽元素的單冒號表示。后來的結(jié)果大家都知道,因?yàn)榈桶姹綢E對雙冒號的兼容問題,幾乎所有的CSSer在寫樣式的時(shí)候都不約而同的使用了單冒號。這無形中,讓這種混淆延續(xù)了下來。而CSS3新偽元素的使用到目前為止,還遠(yuǎn)遠(yuǎn)不成氣候。
偽類和偽元素使用上需要注意的地方
明白其不同之后,就需要注意和考慮在實(shí)際使用上的一些問題。比如:偽類和偽元素的選擇器特殊性(優(yōu)先級)如何計(jì)算?
我在之前的 CSS選擇器距離無關(guān) 一文中,翻譯過CSS標(biāo)準(zhǔn)的計(jì)算選擇器的特殊性這一部分,看完那部分,答案就清楚了:除了否定偽類的特殊規(guī)定外,分開各自作為真正的類和元素計(jì)算。
雖然標(biāo)準(zhǔn)以后的版本可能會允許選擇器多偽元素的情況,但就目前為止,偽元素在一個(gè)選擇器里只能出現(xiàn)一次,并且只能出現(xiàn)在末尾。實(shí)則,偽元素是選中了某個(gè)元素的符合邏輯的某個(gè)實(shí)際卻不存在的部分,所以應(yīng)用中也不會有人將其誤寫成多個(gè)。偽類則是像真正的類一樣發(fā)揮著類的作用,沒有數(shù)量上的限制,只要不是相互排斥的偽類,也可以同時(shí)使用在相同的元素上。關(guān)于CSS3選擇器的詳細(xì)解釋,推薦 rogerjohansson 的 CSS 3 selectors explained。
結(jié)束語
本來只是想稍稍寫點(diǎn),不想話又多了…到了最后,我一度覺得自己還漏了很多,不斷在腦海里搜索,但可能只能下次在補(bǔ)充了。寫這篇的目的是為下篇《CSS偽類與CSS偽元素的典型應(yīng)用》做個(gè)鋪墊,不想理論的東西一寫自己就開始廢話連篇了,慚愧…回看本篇,自己的思路跳的有些亂了,洋洋灑灑這么多字,可能概括起來沒幾句話,但如果希望盡可能表達(dá)清楚,則又免不了冗余過頭。理論總是顯得枯燥了些,下篇閑談應(yīng)用應(yīng)該不至于這么沉悶:)
無論是偽類還是偽元素,都屬于CSS選擇器的范疇。所以它們的定義可以在CSS標(biāo)準(zhǔn)的選擇器章節(jié)找到。分別是 CSS2.1 Selectors 和 CSS Selector Level 3,兩者都已經(jīng)是推薦標(biāo)準(zhǔn)。
標(biāo)準(zhǔn)的定義
在CSS2.1里,5.10 Pseudo-elements and pseudo-classes 描述了這兩個(gè)概念的由來,它們是被一同提及的。但到了 Selector Level 3 里,它們就被分開到兩個(gè)小節(jié)里加以區(qū)分。但無論如何,偽類和偽元素的引入都是因?yàn)樵谖臋n樹里有些信息無法被充分描述,比如CSS沒有“段落的第一行”之類的選擇器,而這在一些出版場景里又是必須的。用標(biāo)準(zhǔn)里的話說:
CSS introduces the concepts of pseudo-elements and pseudo-classes to permit formatting based on information that lies outside the document tree.
簡單翻譯一下,就是:
CSS 引入偽類和偽元素的概念是為了實(shí)現(xiàn)基于文檔樹之外的信息的格式化
這么說很抽象,其實(shí)就是為了描述一些現(xiàn)有CSS無法描述的東西。缺少什么,則引入什么,不管是標(biāo)準(zhǔn),還是人,都是如此成長而來。
偽類與偽元素的區(qū)別
這里我大可以列一個(gè)表格,把所有的偽類和偽元素分開羅列,但這未免太形式化,與其記住“哪些是哪些不是”,不如真正地加以區(qū)分。偽類和偽元素本身就有一個(gè)根本的不同之處,這點(diǎn)直接體現(xiàn)在了標(biāo)準(zhǔn)的描述語句上。
先看一個(gè)偽元素 first-line 例子?,F(xiàn)在有一段HTML,內(nèi)容是一個(gè)段落:
復(fù)制代碼
代碼如下:<p>I am the bone of my sword. Steel is my body, and fire is my blood.
I have created over a thoustand blades.
Unknown to Death.Nor known to Life. Have withstood pain to create many weapon.
Yet, those hands will never hold anything. So as I pray, unlimited blade works.</p>
如果我要描述這個(gè)段落的第一行,在不用偽元素的情況下,我會怎么做?想來我一定要嵌套一層 span,然后加上類名:
復(fù)制代碼
代碼如下:<p><span class="first-line">I am the bone of my sword. Steel is my body, and fire is my blood. </span>
I have created over a thoustand blades.
Unknown to Death.Nor known to Life. Have withstood pain to create many weapon.
Yet, those hands will never hold anything. So as I pray, unlimited blade works.</p>
再反觀一個(gè)偽類 first-child 的例子,有一個(gè)簡單的列表:
復(fù)制代碼
代碼如下:<ul>
<li></li>
<li></li>
</ul>
如果我要描述 ul 的第一個(gè)元素,我無須嵌套新的元素,我只須給第一個(gè)已經(jīng)存在的 li 添加一個(gè)類名就可以了:
復(fù)制代碼
代碼如下:<ul>
<li class="first-child"></li>
<li></li>
</ul>
盡管,第一行和第一個(gè)元素,這兩者的語意相似,但最后作用的效果卻完全不同。所以,偽類和偽元素的根本區(qū)別在于:它們是否創(chuàng)造了新的元素(抽象)。從我們模仿其意義的角度來看,如果需要添加新元素加以標(biāo)識的,就是偽元素,反之,如果只需要在既有元素上添加類別的,就是偽類。而這也是為什么,標(biāo)準(zhǔn)精確地使用 “create” 一詞來解釋偽元素,而使用 “classify” 一詞來解釋偽類的原因。一個(gè)描述的是新創(chuàng)建出來的“幽靈”元素,另一個(gè)則是描述已經(jīng)存在的符合“幽靈”類別的元素。
偽類一開始單單只是用來表示一些元素的動態(tài)狀態(tài),典型的就是鏈接的各個(gè)狀態(tài)(LVHA)。隨后CSS2標(biāo)準(zhǔn)擴(kuò)展了其概念范圍,使其成為了所有邏輯上存在但在文檔樹中卻無須標(biāo)識的“幽靈”分類。
偽元素則代表了某個(gè)元素的子元素,這個(gè)子元素雖然在邏輯上存在,但卻并不實(shí)際存在于文檔樹中。
偽類和偽元素混淆的由來
最為混淆的,可能是大部分人都將 :before 和 :after 這樣的偽元素隨口叫做偽類,而且即使在概念混淆的情況下,實(shí)際使用上也毫無問題——因?yàn)榧词垢拍罨煜?,對真正使用也不會造成多少麻?)
CSS Selector Level 3 為了區(qū)分這兩者的混淆,而特意用冒號加以區(qū)分:
偽類用一個(gè)冒號表示 :first-child
偽元素則使用兩個(gè)冒號表示 ::first-line
并且規(guī)定,瀏覽器既要兼容CSS1和2里既存的偽元素的單冒號表示,同時(shí)又要不兼容CSS3新引入的偽元素的單冒號表示。后來的結(jié)果大家都知道,因?yàn)榈桶姹綢E對雙冒號的兼容問題,幾乎所有的CSSer在寫樣式的時(shí)候都不約而同的使用了單冒號。這無形中,讓這種混淆延續(xù)了下來。而CSS3新偽元素的使用到目前為止,還遠(yuǎn)遠(yuǎn)不成氣候。
偽類和偽元素使用上需要注意的地方
明白其不同之后,就需要注意和考慮在實(shí)際使用上的一些問題。比如:偽類和偽元素的選擇器特殊性(優(yōu)先級)如何計(jì)算?
我在之前的 CSS選擇器距離無關(guān) 一文中,翻譯過CSS標(biāo)準(zhǔn)的計(jì)算選擇器的特殊性這一部分,看完那部分,答案就清楚了:除了否定偽類的特殊規(guī)定外,分開各自作為真正的類和元素計(jì)算。
雖然標(biāo)準(zhǔn)以后的版本可能會允許選擇器多偽元素的情況,但就目前為止,偽元素在一個(gè)選擇器里只能出現(xiàn)一次,并且只能出現(xiàn)在末尾。實(shí)則,偽元素是選中了某個(gè)元素的符合邏輯的某個(gè)實(shí)際卻不存在的部分,所以應(yīng)用中也不會有人將其誤寫成多個(gè)。偽類則是像真正的類一樣發(fā)揮著類的作用,沒有數(shù)量上的限制,只要不是相互排斥的偽類,也可以同時(shí)使用在相同的元素上。關(guān)于CSS3選擇器的詳細(xì)解釋,推薦 rogerjohansson 的 CSS 3 selectors explained。
結(jié)束語
本來只是想稍稍寫點(diǎn),不想話又多了…到了最后,我一度覺得自己還漏了很多,不斷在腦海里搜索,但可能只能下次在補(bǔ)充了。寫這篇的目的是為下篇《CSS偽類與CSS偽元素的典型應(yīng)用》做個(gè)鋪墊,不想理論的東西一寫自己就開始廢話連篇了,慚愧…回看本篇,自己的思路跳的有些亂了,洋洋灑灑這么多字,可能概括起來沒幾句話,但如果希望盡可能表達(dá)清楚,則又免不了冗余過頭。理論總是顯得枯燥了些,下篇閑談應(yīng)用應(yīng)該不至于這么沉悶:)
相關(guān)文章
詳解如何使用CSS3中的結(jié)構(gòu)偽類選擇器和偽元素選擇器
這篇文章主要介紹了詳解如何使用CSS3中的結(jié)構(gòu)偽類選擇器和偽元素選擇器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面2020-01-06- CSS偽元素能使我們添加案定的HTML元素之外的元素,這里我們就來解析CSS中的偽元素及其與偽類的區(qū)別,需要的朋友可以參考下2016-06-27
- 這篇文章主要介紹了詳解CSS中的偽類與偽元素及二者間的區(qū)別,實(shí)際上CSS3中規(guī)范了一種簡單粗暴的方法,即偽類前用一個(gè)冒號表示,而偽元素前用兩個(gè)冒號表示,這樣就不容易混淆了,2016-04-28
- 本文向大家展示了CSS的偽類與偽元素,介紹的非常全面,這里推薦給大家參考下。2014-12-04
- 偽類和偽元素不是真正意義上的html存在的類和元素,他們的存在是為了方便對狀態(tài)和位置進(jìn)行樣式定義。具體他們之間有什么區(qū)別呢,這就是今天我們需要討論的問題了2014-11-23
- 無論是偽類還是偽元素,都屬于CSS選擇器的范疇。所以它們的定義可以在CSS標(biāo)準(zhǔn)的選擇器章節(jié)找到。分別是 CSS2.1 Selectors 和 CSS Selector Level 3,兩者都已經(jīng)是推薦標(biāo)準(zhǔn)2014-09-04
- CSS偽類及偽元素選擇器,如超鏈接的a:link、a:visited、a:hover等等,本文整理了一些,喜歡的朋友可以收藏下2013-11-27
- css偽類偽元素域高級選擇器的介紹,需要的朋友可以參考一下2013-02-26
- 這篇文章主要介紹了淺談CSS 偽元素&偽類的妙用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)2020-09-01