伪类与伪元素

伪类与伪元素

我们先来了解一下两者的官方定义,可以见 伪元素和伪类,简单的总结一下就是

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
2
3
4
var div = document.querySelector('div')

// 获取 before 伪元素的字号大小(获取的时候使用 : 或者 :: 都是可以的)
var fontSize = window.getComputedStyle(div, '::before').getPropertyValue('content')

更改伪元素值

虽然上面的方法可以获取到伪元素的属性值,但是却无法更改,如果使用 JavaScript 来更改伪元素属性值的话,这里主要介绍下面两种方法

更改 data-* 属性值来更改伪元素的 content 值

data-*HTML5 新增的 DOM 元素属性,作用大致可以理解为标记,伪元素的 content 属性值除了常规赋值外,还有一种特殊的 attr() 方法来获取

1
<div class="test" data-text="AAA" data-color="red"></div>
1
2
3
.test::before {
content: attr(data-text) /* AAA */
}

另外 content 其实可以多个 attr 连写,而且 attr() 内的可以是 DOM 元素的任意属性(比如 class 等,甚至非 W3C 标准属性也支持,不过不推荐这么做)

1
2
3
4
/* 注意用空格连接,不要用 + 号拼接 */
.test::before {
content: '类名是' attr(class) '颜色是' attr(data-color)
}

需要注意,目前只有 content 属性支持 这个方法

创建多个 class,通过切换 class 来达到改变样式的目的

这个方法的优点是简单好用且无兼容性问题,缺点是多了一些其实用处不大的 class

参考

# CSS

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×