如何使用:before和:after伪元素?

如果你有一直密切关注各个关于网页设计的博客,你大概会注意到,:before和:after伪元素已经在前端开发界得到越来越多的关注,并且是有很好的理由。特别是,有个博主(位于伦敦的一位开发者Nicolas Gallagher ),他对伪元素的应用尝试,给伪元素带来震撼的曝光机会。

这84个GUI图标是用伪元素和语义化的HTML创建的。查看demo

为了补充和加强本次的曝光(并利用发展趋势带来的好处),我整理了一份自认为比较完整的关于伪元素的“前世今生”。本文针对那些见识过伪元素一些应用的酷炫效果,想自己尝试做,但是要先了解这门CSS技术的读者。

虽然CSS规则包括其它的伪元素,但是在本文,当我提到伪元素的时候,我特别指的是:before和:after这两个。

伪元素是做什么的?

伪元素所做的就像它的字面意思一样,它创造一个虚假的元素,并把它插到目标元素里面内容的之前和之后。

基本语法

:before和:after伪元素的代码很容易编写,这是个例子:

1
2
3
4
5
6
7
#example:before {
content: "#";
}

#example:after {
content: ".";
}

关于这个例子,要注意两点。

第一,我们同时用:before和:after对同样的目标元素起作用。如它们都作用于id为example的元素上。

第二,如果没有content属性(它是生成内容模型所定义的一部分),伪元素是无效的。也就是,如果要使用伪元素选择器来定义,那么就需要有content属性,否则你加任何其它的样式属性都是无意义的。

在这个例子里,将会有伪内容,显示于id为example的元素的内容之前或/和之后。

关于这个语法,要强调几点。

可以给content属性留空,创建一个“零内容”的盒子。如下:

1
2
3
4
5
6
#example:before {
   content: "";
   display: block;
   width: 100px;
   height: 100px;
}

但是,content这个标签是不能被移除的,否则,伪元素就不起作用了。这个“零内容”,需要给content属性一个空内容的双引号。

你也许会注意到,:before和:after也可以写为::before和::after,其实这两者没有什么区别,只是用在CSS3中来区分伪类(单冒号)和伪元素(双冒号)。

最后一点要说明的是,你可以应用一个伪元素,没有作用于任何的目标元素。如下:

1
2
3
:before {
   content: "#";
}

这个是有效的写法,但是一点用处也没有。

插入内容有什么特性?

如上描述,插入的内容在页面的源代码是看不到的。它只在CSS里面可见。

同样,插入的内容默认的是一个内联(inline)元素。所以,要给插入元素一个height\padding\Margin等,需要先给元素定义为块状(block级)的元素。

以下就开始简单描述如何定义伪元素。

styles-pseudo-elements

styles-pseudo-elements

在这个例子里面,我对应用到插入元素的样式进行了高亮。伪元素就是这样的独特,即是可以在同样的声明块中同时定义插入内容和样式。

另外,要知道的一点是,CSS的继承规则同样适用于插入元素。比如应用在body里面的字体、字体大小等这些样式,插入元素和其它元素一样,会继承这样的样式。

同样,和其他元素一样,伪元素不继承父级如padding\margin这样的属性。

插入在什么之前和之后?

你或许会迷惑,插入元素是插入到哪里?你一看到:before和:after或许会认为就是在其所作用的目标元素的之前或之后。然而,事实并不是这样。

要插入的内容,会被放置于目标元素的里面,作为它的一个子元素,并且它会显示在目标元素里面内容的之前或之后。

要理解这点,看看这个代码:

1
2
<p class=box>Other content.
</p>

样式:

1
2
3
4
5
6
7
8
9
10
11
p.box {
   width: 300px;
   border: solid 1px white;
   padding: 20px;
}
p.box:before {
   content: "#";
   border: solid 1px white;
   padding: 2px;
   margin: 0 10px 0 0;
}

在HTML里面,你所看到的是个段落(p),这个p有个class为box,其里面的内容是“other content”(就像你会在html的源代码里面所看到的)。在CSS里面,这个p被定义样式有width\padding\border。

然后,再看看伪元素的定义。在这个例子里面,这个插入内容是放到到段落(p)里面的内容之前的。被定义的样式有border\padding\margin。

看看这个图就明白了。

Before Or After What?

Before Or After What?

外框是段落,内容插到段落里面内容的前面而不是到段落的前面。

插入非文本的内容

我之前提过可以给content属性设为空字符,或者一个文本内容。其实你还有其它的两种选择,就是给它加特定的内容,如下:

第一,可以包含一个URL指向一个图片,在这里,你可以定义一个Data URI,就像你想定义一个背景图片一样。

1
2
3
p:before {
   content: url(image.jpg);
}

第二,你还有另外一个选择就是加上attr(x)这种形式的函数。根据定义,这个函数为选择器对象返回一个由属性X的值生成的字符串

1
2
3
a:after {
   content: attr(href);
}

attr()函数取得所定义的属性的值,并把它作为文本变成可以插入的伪内容。

浏览器支持情况

像对待其它的一些前端技术一样,开发者们关注的重点之一就是浏览器支持啦。在这点上,看似问题还没那么大。:before和:after的浏览器支持情况如下:

Chrome 2+,
Firefox 3.5+ (3.0有部分支持),
Safari 1.3+,
Opera 9.2+,
IE8+ (尚有些小bug),
大部分的移动设备浏览器。

这里唯一真正的问题(毫无疑问)就是完全不支持的IE6和IE7。所以,如果你的目标用户是网页开发者群(或者其它较少使用IE浏览器的群体),那么你就大胆用吧。

另外,说到伪元素的安全性,幸运的是,缺乏一个伪元素并不会引发什么功能上的问题。伪元素大多数是用来生成修饰性的内容,在不支持伪元素的浏览器里面,不会引发重大问题。所以,如果你的目标群体是IE浏览器使用者占大多数的,在某个程度上,你依然可以使用这个属性。

几个提醒

如前面所述,伪元素的内容不会在DOM结构中显示。这些元素不是真正的元素。它们在大多数的辅助设备中是不可访问的。所以对网页的使用性和可用性很关键的内容,要尽量避免使用伪元素来生成。

另外,像Firebug这样的开发者工具,并不会显示由伪元素生成的内容。所以,如果滥用伪元素,会引发网页调试过程效率低下和网页维护不方便等问题。

([更新]在评论里提及的两点:你可以使用chrome的开发者工具来查看关于伪元素的样式,但这个元素不显示在DOM里面。还有一点,Firebug1.8已经添加了对伪元素的支持。)

原文地址:https://www.cnblogs.com/guozhe/p/2376992.html