探究伪元素及其用途

之前也或多或少看过一些关于伪元素的资料,有些许了解。这两天练手时遇到相关的实现较多,特再查找一些资料,看过后进行总结。内容包括伪类与伪元素的区别、伪元素的优点和一些伪元素的实际应用,目标是一篇文章基本讲通。

伪类与伪元素的区别

伪元素(Pseudo-elements)容易与伪类(Pseudo-classes)混淆。在 w3c 定义中,伪类用于向某些选择器添加特殊的效果,而伪元素用于将特殊的效果添加到某些选择器。可以看到从定义上来说,二者确实不好分辨。不过在种类上可以看出二者的一些不同。

伪类包括:

  • :link:向未被访问的链接添加样式。
  • :visited:向已被访问的链接添加样式。
  • :hover:当鼠标悬浮在元素上方时,向元素添加样式。
  • :active:向被激活的元素添加样式。
  • :focus:向拥有键盘输入焦点的元素添加样式。
  • :first-child:向元素的第一个子元素添加样式。
  • :lang:向带有指定 lang 属性的元素添加样式。

其中前四个因为用不同的方式显示链接的不同状态,被称为“锚伪类”。在 CSS 定义中,a:hover必须被置于 a:linka:visited之后,而a:active必须被置于a:hover之后才是有效的。

伪元素包括:

  • :before:在元素之前添加内容。
  • :after:在元素之后添加内容。
  • :first-letter:向文本的第一个字母添加特殊样式。
  • :first-line:向文本的首行添加特殊样式。

其中前两个无疑是用的最多的。后两个也可以用于实现一些特殊效果,例如通过:first-letter实现段落首字母加粗或变色。

两者的根本区别是:伪类可以通过直接添加一个实际的类样式达到同等效果;而伪元素的效果则需要先添加一个实际的元素,再在元素上添加样式才能达到。

在 CSS 3 中修订后的伪元素使用两个冒号(::)以与伪类进行区分。但无论使用单冒号还是双冒号,浏览器都能识别。并且 IE 8 只支持单冒号的写法。因此为了更广泛的浏览器兼容性,还是推荐使用单冒号的写法。

伪元素的优点

最常使用的两种伪元素——:before:after可以在内容元素的前后插入额外的元素。通过伪元素,在实现很多炫酷的视觉效果时,我们不必修改现有的 HTML 文档结构。因为 HTML 文档本身仅仅应该包含内容,而不应该包含样式,所以伪元素更应该被提倡。

伪元素的应用

鉴于伪元素应用很多时候代码相对专一,建议配合 Sass,通过设置 mixin 来使用以提高复用性(你可以通过我的上一篇博文 初见Sass-便捷的CSS预处理器 来了解Sass)。

清除浮动

这大概是伪元素最为常见的应用了。比起插入额外的非语义标记来清除内联元素的浮动,这种俗称“clearfix”的方式更语义化。

CSS

1
2
3
4
5
6
7
8
9
10
11
12
.group:before,
.group:after {
content:"";
display:table;
}
.group:after {
clear:both;
overflow: hidden;
}
.group {
zoom:1; /* For IE 6/7 (trigger hasLayout) */
}

Sass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@mixin clearfix {
@if $legacy-support-for-ie {
*zoom: 1;
}
&:before,
&:after {
content: "";
display: table;
}
&:after {
clear: both;
overflow: hidden;
}
}
// 通过 @include 方法调用

实现样式效果

能够借助伪元素实现的样式效果数不胜数。这里举一个简单而常用的例子。

很多时候我们会在每一节的标题下做一个类似下划线效果,用来强调。使用伪元素可以让我们不必添加额外的元素来实现这个效果。

Sass 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@mixin section-title() {
font-size: 2em;
padding: 2em 0;
text-transform: uppercase;
color: #55a2dd;
&:after {
display: block;
content: "";
background-color: #cccccc;
width: 2em;
height: .2em;
margin: .4em auto;
}
}

设置透明度

有时我们想给一张大图设置透明度,却发现其子元素都会被继承这个透明度。以往想要消除这个属性总让我头大。现在通过伪元素,我们就可以分别为文字和图片设置不同的透明度。

Sass 代码如下(来自第3周:设计你自己的页面):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
.hero {
width: 100%;
min-height: 50em;
position: relative;
background-color: $mask-color;
z-index: 1;
&:after {
background: url('../images/hero-1-resized.jpg');
background-size: cover;
position: absolute;
content: "";
z-index: -1;
opacity: .2;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
h2 {
font-size: 6em;
font-weight: bold;
padding: 3em 0 1em 0;
text-transform: uppercase;
color: white;
}
p {
max-width: 70%;
font-size: 1.5em;
font-weight: lighter;
color: #cecece;
line-height: 1.4;
margin: 0 auto;
padding: 1em 0 8em 0;
span {
color: $heading-color;
}
}
}

对于 .hero 这个 section,我们将其背景设置为灰色,并将 position 设置为 relative。然后为其添加了一个伪元素,这个伪元素上包含了实际的图片,并为图片设置了透明度 .2。

参考资料

CSS 伪元素 - W3School

你可以从这篇文章中了解更多伪元素的应用:大放异彩的伪元素——可以做什么?