字面上区分
伪类和伪元素都有一个共同的修饰词“伪”,“伪”是什么意思?就是假的呗。所以伪类就是假的类,伪元素就是假的元素,这就是在字面上区分它们。那么我们再进一步更好的区分一下。
伪类
伪类存在的意义是为了通过选择器,格式化DOM树以外的信息以及不能被常规CSS选择器获取到的信息。(CS3给出的定义,翻译过来)
所以我们从上面知道伪类的功能有两个:
- 格式化DOM树以外的信息。比如:
<a>
标签的:link、:visited
等。这些信息都不存在于DOM树中。 - 格式化不能被常规CSS选择器获取到的信息。比如:要获取第一个子元素,我们无法用常规的CSS选择器获取到,但是可以用
:first-child
来获取到。
伪类例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
p:first-of-type {
color: red; // <p>标签的内容变为红色
}
</style>
</head>
<body>
<div class="one">
<h1>h1文本</h1>
<p>p文本</p>
<p>第二个p文本</p>
</div>
</body>
</html>
这里我们可以看到伪类弥补了选择器的不足,让我们可以专门操作第一个子元素。
伪元素
伪元素可以创建一些文档语言无法创建的虚拟元素。 比如:文档语言没有一种机制可以描述元素内容的第一个字母或第一行,但伪元素可以做到(::first-letter、::first-line
)。同时,伪元素还可以创建源文档不存在的内容,比如使用 ::before
或 ::after
。(CS3给出的定义,翻译过来)
伪元素例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.first-letter {
color: red; //首个字母会变红色
}
</style>
</head>
<body>
<p>
<span class="first-letter">H</span>ello, World
</p>
</body>
</html>
和下面这段代码得出的结果也是一样的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
p::first-letter {
color: red;
}
</style>
</head>
<body>
<p>
Hello, World
</p>
</body>
</html>
而伪元素本质上是创建了一个虚拟容器(元素),我们可以在其中添加内容或样式。
所以简单来说,区分伪类和伪元素就是:伪类是相当于给元素添加一个类选择器,而伪元素就是给元素添加一个标签,使得它们能够更准确容易被操作(添加样式等)。(我自己的理解)
除了上面这个本质区别以外,在CSS3中,伪类用单冒号:表示;而伪元素用双冒号::表示。一个选择器可以同时使用多个伪类(但有的伪类会互斥);而一个选择器只能同时使用一个伪元素(未来的版本可能会支持多伪元素)。
:before和::before的区别
一看到这个我还有点懵逼,这是乍回事啊,不是才刚说完单引号和双引号用来区分伪类和伪元素吗?::before不是伪元素吗?::before 代表生成的内容元素,表示相应元素的可抽象样式的第一个子元素,即:所选元素的第一个子元素 利用::before可以把需插入的内容插入到元素的其他内容之前,并且默认内联显示。::before需要使用content属性来指定内容的值。这就把我搞晕了,所以我又去查了一下,发现这是CSS版本问题。
单冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素。伪元素和伪类之所以这么容易混淆,是因为他们的效果类似而且写法相仿,但实际上 css3 为了区分两者,已经明确规定了伪类用一个冒号来表示,而伪元素则用两个冒号来表示。但因为兼容性的问题,所以现在大部分还是统一的单冒号,但是抛开兼容性的问题,我们在书写时应该尽可能养成好习惯,区分两者。
双冒号是在当前规范中引入的,用于区分伪类和伪元素。不过浏览器需要同时支持旧的已经存 在的伪元素写法,比如:first-line、:first-letter、:before、:after等,而新的在CSS3中引入的伪元素则不允许再支持旧的单冒号的写法。
那么现在就可以完整的回答标题中的问题了,对于CSS2之前已有的伪元素,比如:before,单冒号和双冒号的写法::before作用是一样的。
所以,如果你的网站只需要兼容webkit、firefox、opera等浏览器,建议对于伪元素采用双冒号的写法,如果不得不兼容IE浏览器,还是用CSS2的单冒号写法比较安全。
新增伪类有哪些
- :link、:visited、:hover、:active 这四个比较简单就不多说了(在 CSS 定义中,a:hover 必须被置于 a:link 和 a:visited 之后,才是有效的。a:active 必须被置于 a:hover 之后,才是有效的。)
- :first-of-type p:first-of-type 选择属于其父元素的首个
<p>
元素的每个<p>
元素。 - :last-of-type p:last-of-type 选择属于其父元素的最后
<p>
元素的每个<p>
元素。 - :only-of-type p:only-of-type 选择属于其父元素唯一的
<p>
元素的每个<p>
元素。 - :only-child p:only-child 选择属于其父元素的唯一子元素的每个
<p>
元素。 - :nth-child(n) p:nth-child(2) 选择属于其父元素的第二个子元素的每个
<p>
元素。 - :nth-last-child(n) p:nth-last-child(2) 同上,从最后一个子元素开始计数。
- :nth-of-type(n) p:nth-of-type(2) 选择属于其父元素第二个
<p>
元素的每个<p>
元素。 - :nth-last-of-type(n) p:nth-last-of-type(2) 同上,但是从最后一个子元素开始计数。
- :last-child p:last-child 选择属于其父元素最后一个子元素每个
<p>
元素。 - :root :root 选择文档的根元素。
- :empty p:empty 选择没有子元素的每个
<p>
元素(包括文本节点)。 - :target #news:target 选择当前活动的 #news 元素。
- :enabled input:enabled 选择每个启用的
<input>
元素。 - :disabled input:disabled 选择每个禁用的
<input>
元素 - :checked input:checked 选择每个被选中的
<input>
元素。 - :not(selector) :not§ 选择非
<p>
元素的每个元素。 - ::selection ::selection 选择被用户选取的元素部分。
这里面新增的伪类挺多的,一开始看几遍过不久就忘了,所以就自己写个博客存起来,忘记就过来看看_。
常用伪元素
- ::before 该伪元素定义在元素之前添加内容
- ::after 该伪元素定义在元素之后添加内容
- ::first-line 该伪元素向文本的首行添加特殊样式
- ::first-letter 该伪元素向文本的第一个字母添加特殊样式
本文参考了以下文章: