我们先来了解一下两者的官方定义,可以见 伪元素和伪类,简单的总结一下就是
CSS 引入伪类和伪元素概念是为了格式化文档树以外的信息,也就是说,伪类和伪元素的作用主要是用来修饰不在文档树中的部分,两者的区别如下
- 伪类用于当已有元素处于的某个状态时,为其添加对应的样式,这个状态是根据用户行为而动态变化的
- 比如说,当用户悬停在指定的元素时,我们可以通过
:hover来描述这个元素的状态
- 比如说,当用户悬停在指定的元素时,我们可以通过
- 伪元素用于创建一些不在文档树中的元素,并为其添加样式
- 比如说,我们可以通过
:before来在一个元素前增加一些文本,并为这些文本添加样式 - 虽然用户可以看到这些文本,但是这些文本实际上不在文档树中
- 比如说,我们可以通过
简单的总结就是
- 伪类的操作对象是文档树中已有的元素
- 而伪元素则创建了一个文档数外的元素
两者的区别主要在于有没有创建一个文档树之外的元素,具体可见下图

伪元素是使用单冒号还是双冒号?
CSS3 规范中的要求使用双冒号(::)表示伪元素,以此来区分伪元素和伪类
- 比如
::before和::after等伪元素使用双冒号(::) :hover和:active等伪类使用单冒号(:)
除了一些低于 IE8 版本的浏览器外,大部分浏览器都支持伪元素的双冒号(::)表示方法,然而,除了少部分伪元素,如 ::backdrop 必须使用双冒号,大部分伪元素都支持单冒号和双冒号的写法,比如 ::after,写成 :after 也可以正确运行
那么我们到底应该是使用单冒号还是双冒号呢?我们可以参考 MDN 得知,大概的意思就是,虽然 CSS3 标准要求伪元素使用双冒号的写法,但也依然支持单冒号的写法(为了向后兼容,建议你在目前还是使用单冒号的写法),实际上,伪元素使用单冒号还是双冒号很难说得清谁对谁错,你可以按照个人的喜好来选择某一种写法
下面我们再来看看一些操作伪元素的方式,比如如何获取并修改伪元素的值
获取伪元素的值
这里主要涉及 ::before 和 ::after,其余几个伪元素(::first-letter、::first-line、::selection 等)由于没有 content 属性,所以一笔带过,本质上是一样的,由于 JavaScript 里没有可以直接操作伪元素的选择符,但是我们可以通过获取其 CSS 属性的方法来达到目的,这里可以利用 window.getComputedStyle 方法选择到伪元素,然后利用 getPropertyValue 方法获取对应的属性的值
1 | window.getComputedStyle(element[, pseudoElt]) |
此方法包含两个参数,一个是元素本身另一个是元素的伪元素
1 | var div = document.querySelector('div') |
更改伪元素值
虽然上面的方法可以获取到伪元素的属性值,但是却无法更改,如果使用 JavaScript 来更改伪元素属性值的话,这里主要介绍下面两种方法
更改 data-* 属性值来更改伪元素的 content 值
data-* 是 HTML5 新增的 DOM 元素属性,作用大致可以理解为标记,伪元素的 content 属性值除了常规赋值外,还有一种特殊的 attr() 方法来获取
1 | <div class="test" data-text="AAA" data-color="red"></div> |
1 | .test::before { |
另外 content 其实可以多个 attr 连写,而且 attr() 内的可以是 DOM 元素的任意属性(比如 class 等,甚至非 W3C 标准属性也支持,不过不推荐这么做)
1 | /* 注意用空格连接,不要用 + 号拼接 */ |
需要注意,目前只有
content属性支持 这个方法
创建多个 class,通过切换 class 来达到改变样式的目的
这个方法的优点是简单好用且无兼容性问题,缺点是多了一些其实用处不大的 class