转贴:CSS伪类与CSS伪元素的区别及由来具体说明

关于二者的区别,实际上是很古老的问题。可是时至今日,因为各类网络误传以及一些不负责任的书籍误笔,仍然有至关多的人将伪类与伪元素混为一谈,甚至不乏不少CSS老手。早些年刚入行的时候,我本身也被深深误导,由于论坛里的帖子大多不关心这种概念的细微差异,即便有人出来讲一句:“这两个是不一样的”,也只是被更多的帖子淹没掉而已。因此以为有必要写下这些我所知的部分,这里着重写的是为何这二者不一样,以及一些平时容易错过的细节。 

不管是伪类仍是伪元素,都属于CSS选择器的范畴。因此它们的定义能够在CSS标准的选择器章节找到。分别是 CSS2.1 Selectors 和 CSS Selector Level 3,二者都已是推荐标准。 
标准的定义 

在CSS2.1里,5.10 Pseudo-elements and pseudo-classes 描述了这两个概念的由来,它们是被一同说起的。但到了 Selector Level 3 里,它们就被分开到两个小节里加以区分。但不管如何,伪类和伪元素的引入都是由于在文档树里有些信息没法被充分描述,好比CSS没有“段落的第一行”之类的选择器,而这在一些出版场景里又是必须的。用标准里的话说: 
CSS introduces the concepts of pseudo-elements and pseudo-classes to permit formatting based on information that lies outside the document tree. 
简单翻译一下,就是: 
CSS 引入伪类和伪元素的概念是为了实现基于文档树以外的信息的格式化 
这么说很抽象,其实就是为了描述一些现有CSS没法描述的东西。缺乏什么,则引入什么,不论是标准,仍是人,都是如此成长而来。 

伪类与伪元素的区别 
这里我大能够列一个表格,把全部的伪类和伪元素分开罗列,但这未免太形式化,与其记住“哪些是哪些不是”,不如真正地加以区分。伪类和伪元素自己就有一个根本的不一样之处,这点直接体如今了标准的描述语句上。 
先看一个伪元素 first-line 例子。如今有一段HTML,内容是一个段落: 

php

复制代码
代码以下:

<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> 


若是我要描述这个段落的第一行,在不用伪元素的状况下,我会怎么作?想来我必定要嵌套一层 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>


再反观一个伪类 first-child 的例子,有一个简单的列表: 

网络

复制代码
代码以下:

<ul>
<li></li>
<li></li>
</ul>


若是我要描述 ul 的第一个元素,我无须嵌套新的元素,我只须给第一个已经存在的 li 添加一个类名就能够了: 

ide

复制代码
代码以下:

<ul>
<li class="first-child"></li>
<li></li>
</ul>


尽管,第一行和第一个元素,这二者的语意类似,但最后做用的效果却彻底不一样。因此,伪类和伪元素的根本区别在于:它们是否创造了新的元素(抽象)。从咱们模仿其意义的角度来看,若是须要添加新元素加以标识的,就是伪元素,反之,若是只须要在既有元素上添加类别的,就是伪类。而这也是为何,标准精确地使用 “create” 一词来解释伪元素,而使用 “classify” 一词来解释伪类的缘由。一个描述的是新建立出来的“幽灵”元素,另外一个则是描述已经存在的符合“幽灵”类别的元素。 

伪类一开始单单只是用来表示一些元素的动态状态,典型的就是连接的各个状态(LVHA)。随后CSS2标准扩展了其概念范围,使其成为了全部逻辑上存在但在文档树中却无须标识的“幽灵”分类。 
伪元素则表明了某个元素的子元素,这个子元素虽然在逻辑上存在,但却并不实际存在于文档树中。

伪类和伪元素混淆的由来 
最为混淆的,多是大部分人都将 :before 和 :after 这样的伪元素随口叫作伪类,并且即便在概念混淆的状况下,实际使用上也毫无问题——由于即便概念混淆,对真正使用也不会形成多少麻烦:) 
CSS Selector Level 3 为了区分这二者的混淆,而特地用冒号加以区分: 
伪类用一个冒号表示 :first-child 
伪元素则使用两个冒号表示 ::first-line 

而且规定,浏览器既要兼容CSS1和2里既存的伪元素的单冒号表示,同时又要不兼容CSS3新引入的伪元素的单冒号表示。后来的结果你们都知道,由于低版本IE对双冒号的兼容问题,几乎全部的CSSer在写样式的时候都不约而同的使用了单冒号。这无形中,让这种混淆延续了下来。而CSS3新伪元素的使用到目前为止,还远远不成气候。

伪类和伪元素使用上须要注意的地方 
明白其不一样以后,就须要注意和考虑在实际使用上的一些问题。好比:伪类和伪元素的选择器特殊性(优先级)如何计算? 
我在以前的 CSS选择器距离无关 一文中,翻译过CSS标准的计算选择器的特殊性这一部分,看完那部分,答案就清楚了:除了否认伪类的特殊规定外,分开各自做为真正的类和元素计算。 
虽然标准之后的版本可能会容许选择器多伪元素的状况,但就目前为止,伪元素在一个选择器里只能出现一次,而且只能出如今末尾。实则,伪元素是选中了某个元素的符合逻辑的某个实际却不存在的部分,因此应用中也不会有人将其误写成多个。伪类则是像真正的类同样发挥着类的做用,没有数量上的限制,只要不是相互排斥的伪类,也能够同时使用在相同的元素上。关于CSS3选择器的详细解释,推荐 rogerjohansson 的 CSS 3 selectors explained。 

结束语 
原本只是想稍稍写点,不想话又多了…到了最后,我一度以为本身还漏了不少,不断在脑海里搜索,但可能只能下次在补充了。写这篇的目的是为下篇《CSS伪类与CSS伪元素的典型应用》作个铺垫,不想理论的东西一写本身就开始废话连篇了,惭愧…回看本篇,本身的思路跳的有些乱了,洋洋洒洒这么多字,可能归纳起来没几句话,但若是但愿尽量表达清楚,则又免不了冗余过头。理论老是显得枯燥了些,下篇闲谈应用应该不至于这么沉闷:)spa

相关文章
相关标签/搜索