在重构页面时,除了基本的CSS选择器之外,我们经常还会借助伪类和伪元素,来完成一些特殊的需求。可能,你对于这两种写法已经应用的非常熟练了,但是,如果不刻意梳理,还是避免不了这两个概念的混淆!

如果按照W3C的说法,它们两者都是用于描述 CSS 无法表述的内容。而按照我自己的理解,可以归纳为:

伪类:文档中实际存在的元素,我们可以通过DOM访问到它们。它只是针对符合某些条件的元素,使用 “假定” 的类名来匹配它们。

伪元素:伪元素又被称为 幽灵元素,即文档中不存在的元素,DOM无法对其进行访问,它也不是HTML中一个特定的标签。但我们就是可以通过 “虚拟” 的元素来指定它们。

一、常见伪类和伪元素

伪类

伪类大致可分为以下几部分,即:

类别 伪类
状态 link、visited、hover、active、checked、enabled、disabled、empty
结构 first-child、last-child、nth-child、nth-last-child、nth-of-type、nth-last-of-type、only-child、only-of-type、not、target
语言 dir、lang
其他 root、fullscreen

伪元素

相对伪类来说,伪元素则比较少,这里以是否能使用双冒号来分类:

类别 伪元素
单、双冒号均可 before、after、first-letter、first-line
只能双冒号 selection、placeholder、backdrop

二、区别

:::

在css2时,这两个概念本身就模糊不清。我们既可以使用单冒号 : 来表示伪类,也可以用它来表示伪元素。这种单冒号的做法,间接上也导致了概念的混淆。

因此为了加以区分,css3决定伪类使用单冒号 :,比如:

a:hover {}
p:first-child {}
...

而伪元素则使用双冒号 ::,比如:

p::first-line {}
div::before {}
...

但是要注意,因为一些浏览器(IE8以下)不支持双冒号的写法,但为了向下兼容老版浏览器,所以,一些伪元素既支持单冒号写法,又支持双冒号写法。比如 beforeafterfirst-letterfirst-line

除了这些伪元素,有一些伪元素仅且只支持双冒号的写法,比如 selectionplaceholderbackdrop

后面是否能接内容

对于伪类,我们不仅可以在它自身上设置相应的效果。还可以在伪类后面,针对它的子级设置相关样式,比如:

ul li:first-child span {color: red;}

p:hover span {display: none;}

在上面的代码中,第一行,我们首先利用伪类选择 ul 下的第一个 li,再在此基础上匹配对应的 span 元素,再应用相关样式。

第二行则是处理 p 标签鼠标经过时,再将此时状态下,p 标签中的 span 隐藏起来。

但是对于伪元素,你却不能在它后面追加内容,做后续处理。毕竟,伪元素也不会再出现子元素了吧?!

所以,一个选择器上,伪类可以多个使用。但是伪元素,只能使用一个。

概念理解

有些人把 伪类 简单的描述为一种特殊状态或关系,我觉得这种描述很贴切,因为伪类本来就包含 link、visited、hover、active、focus 这些状态,还包括 first-child、last-child、target 等这种结构化的关系。

另外,有些人又把 伪元素 简单理解为创建了一个新的虚拟元素。但这种理解好像说不过去,虽然说 before、after 的确创建了虚拟元素,但是 placeholder、selection、backdrop 又作何理解呢?

三、总结

其实吧,若是从实用角度来看,伪类和伪元素概念混淆了,会影响你页面的开发吗?当然不会!!! 感觉这点和 BFC 有点像了。