这是一个经典的 CSS 面试题,理解伪元素和伪类的区别对于掌握 CSS 选择器至关重要。
核心区别总结
- 伪类 (Pseudo-classes):用于描述一个元素的特定状态或位置。它选择的是已存在的元素,但处于某种特殊条件(如悬停、被点击、第一个子元素等)。
- 伪元素 (Pseudo-elements):用于创建并选择一个虚拟的、不存在于 DOM 中的元素。它通常用来样式化元素的某一部分(如首行、首字母)或插入内容。
简单来说:伪类是“状态”,伪元素是“部分”或“虚拟内容”。
伪类 (Pseudo-classes)
作用:
伪类允许你根据用户的交互行为或元素在文档中的结构位置来应用样式。
常见示例:
- 用户行为/交互状态:
:hover
:当鼠标指针悬停在元素上时。:active
:当元素被激活(如鼠标按下时)。:focus
:当元素获得焦点(如输入框被选中)。:visited
,:link
:针对链接的不同访问状态。
- 结构性/位置性:
:first-child
:作为其父元素的第一个子元素。:last-child
:作为其父元素的最后一个子元素。:nth-child(n)
:匹配父元素的第 n 个子元素。:first-of-type
,:last-of-type
:匹配同类型兄弟元素中的第一个或最后一个。:not(selector)
:匹配不符合指定选择器的元素。
- 表单相关:
:checked
:匹配被选中的<input>
元素(如单选按钮、复选框)。:disabled
,:enabled
:匹配禁用或启用的表单元素。:required
,:optional
:匹配有required
属性或没有的表单元素。
语法特点:使用单个冒号 :
。
a:hover {
color: red;
}
li:first-child {
font-weight: bold;
}
伪元素 (Pseudo-elements)
作用:
伪元素允许你创建一个不属于原始文档树的虚拟元素,并对其进行样式化。它们通常用于装饰性的目的或插入生成的内容。
常见示例:
- ::before 和 ::after:
- 这是最常用的伪元素,用于在元素的内容之前或之后插入生成的内容。必须配合
content
属性使用,否则不会显示。
.quote::before {
content: """;
color: gray;
}
.quote::after {
content: """";
color: gray;
} - 这是最常用的伪元素,用于在元素的内容之前或之后插入生成的内容。必须配合
- ::first-line:
- 选择块级元素的第一行文本。
p::first-line {
font-weight: bold;
color: blue;
} - ::first-letter:
- 选择块级元素的第一个字母(常用于首字下沉效果)。
p::first-letter {
font-size: 2em;
float: left;
margin-right: 0.1em;
} - ::selection:
- 选择用户在页面上选中的文本部分。
::selection {
background-color: yellow;
color: black;
}
- 选择用户在页面上选中的文本部分。
语法特点:现代标准推荐使用双冒号 ::
,以区别于伪类。但为了兼容旧浏览器,单冒号 :
也仍然有效(除了 ::before
和 ::after
在 IE8 只支持单冒号)。
关键区别点对比
特性 | 伪类 (Pseudo-class) | 伪元素 (Pseudo-element) |
---|---|---|
本质 | 描述现有元素的状态或位置 | 创建虚拟的、新的元素 |
选择目标 | 已存在于 DOM 中的元素 | DOM 中不存在的虚拟部分或生成的内容 |
主要用途 | 交互反馈、结构定位 | 装饰性样式、插入内容 |
语法 | 单冒号 : | 推荐双冒号 :: (历史原因单冒号也可用) |
是否生成新元素 | 否 | 是 (视觉上或通过 content ) |
content 属性 | 不适用 | ::before 和 ::after 必须使用 |
面试加分点
- 兼容性:虽然规范推荐
::
,但在实际项目中,由于需要兼容老版本浏览器(特别是 IE8),有时仍会看到单冒号的写法。但在新项目中应优先使用双冒号以明确区分。 - 性能:过度使用复杂的结构性伪类(如
:nth-child
的复杂表达式)可能影响渲染性能。 - 语义清晰:使用双冒号
::
能让代码更具可读性,一眼就能看出是伪元素。
总结回答示例:
伪类用于选择处于特定状态或位置的已有元素,比如
:hover
或:first-child
。而伪元素用于创建一个虚拟的元素来样式化元素的某个部分或插入内容,比如::before
、::after
、::first-letter
。最直观的区别是语法:伪类用单冒号:
,伪元素推荐用双冒号::
。
THE END