神奇的伪元素content属性

伪元素就是在 CSS 文件中选中的,实际上是不存在在 DOM 中的元素,早在 CSS1 的方案中就提出了:first-letter:first-line这两个伪元素(也就是说 IE5.5 这种史前怪兽也可以做首字下沉和首行特效…),在CSS2中则添加了:before:after伪元素,在CSS3中,为了区别伪元素与伪类,则让伪元素使用::作为前缀(IE从 IE9 开始支持 :: 伪元素)。

:before:after这对好兄妹在初登场的时候使用得并不频繁,因为根据 CSS2.1 的描述,它们是用来显示那些作者不希望出现在文档树中,可以让浏览器自动生成的内容:

In some cases, authors may want user agents to render content that does not come from the document tree. One familiar example of this is a numbered list; the author does not want to list the numbers explicitly, he or she wants the user agent to generate them automatically. Similarly, authors may want the user agent to insert the word “Figure” before the caption of a figure, or “Chapter 7” before the seventh chapter title. For audio or braille in particular, user agents should be able to insert these strings.

后来的人们把这些棒棒的 idea 全部弃之不用,反之利用它的特性来完成很多黑科技手法:其主要用法之一是让它们充当 clear fix (清除浮动)以及避免 margin collapse (margin合并)的元素,从而保持干净整洁的 DOM 文档树。另外还有使用伪元素来做 icon (Bootstrap 所使用的 Font Awesome 以及现在绝大多数 @font-face 做 icon 的基本上都是这么做)。后来伴随着 CSS3 所支持的更多效果,慢慢就出现了一些丧病的 绘图,开始看到的是像这样的伪 3D 特效,然后代码死宅们还放出了 One div 这种实用奇特小 icon 和 A Single Div 这种明显就是炫技的作品……

各种情况表明现在这对好兄妹完全是肆无忌惮的泛滥状态,但上面举例这些却只是神奇伪元素的一部分用法——content属性值为字符串或空,从当时来看(乃至现在来看),根本都属于黑科技的一类。但其实伪元素:before:after还有很多其他可选的属性值…而且那才是人家被创造出来的本意啊!!!

quote系列和none

把这俩放一起说是因为我真的看不太出来…这俩有什么用。none还好说,就是清空这个伪元素。一个伪元素如果没有 content 属性就直接消失了,如同它未曾存在过(但是normal的默认值就是等于none,而且这个属性貌似不继承…

quote系列是指open-quote、close-quote、no-open-quote、no-close-quote四个属性值…默认情况下open-quote就会显示为上引号,close-quote会显示为下引号…可以通过父元素的quote属性来为其重新赋值,以配合不同语言的引号需求。翻了一下 W3c 标准的文档,关于 quote 系列的示例如下:

1
2
3
4
5
6
/* 创建不同语言的 quotes 符号 */
q:lang(en) { quotes: '"' '"' "'" "'" }
q:lang(no) { quotes: "«" "»" '"' '"' }
/* 设置伪元素 */
q:before { content: open-quote }
q:after { content: close-quote }

那么当HTML为

1
2
3
4
5
6
7
8
<HTML lang="no">
<HEAD>
<TITLE>Quotes</TITLE>
</HEAD>
<BODY>
<P><Q>Trøndere gråter når <Q>Vinsjan på kaia</Q> blir deklamert.</Q>
</BODY>
</HTML>

的时候,显示结果为:

«Trøndere gråter når “Vinsjan på kaia” blir deklamert.»

这个示例其实解决了我很多疑惑(有问题问标准嗯嗯),从国内环境来说,首先我们缺乏这种转换的需求(就连 zh-hant 和 zh-hans 之间的转换都鲜有问津),其次我们的设计和前端代码里都不会特地区分“某人所说的话”这样的内容…所以(摊手…)如果是多语言网站,并且有这种需求,可以参考。

另外邪道一点的想法就是把 quote 改成各种符号…实用性上没找到什么亮点……

url()

括号里填上随便一个图片、音频、视频的地址,就搞定了。填图片的做法与用 @font-face 做 icon 有些相似,放大图的话又好似 background。如果配合:hover伪类或者[check]这种黑科技的话…倒是可以抛弃js实现一些比较炫酷的声光电一体特效(思路参见使用 radio 实现纯 css slider 的黑科技demo)。

attr()

在括号里填上个属性名,就可以将该伪元素所属的元素的该属性值读出来,返回字符串并作为这个伪元素的内容。常见的做法之一是在 print 页面中,让伪元素读取a元素的href属性,以便用户访问。另外这几天做的一个新 demo 里,需要一个图片悬停出现黑色遮罩和说明文字的效果。于是给图片的父元素设置了两个伪元素,一个用来当作黑色遮罩,另一个则读取单独写入的data-*属性值来作为显示的文字内容~甚至可以丧病地读取多个内容,实现多行内容……

随手写了一个demo,包括了伪元素折行和图片水平分布两个黑科技…欢迎围观和吐槽

BTW, attr()作为 CSS 中为数不多的函数(在 CSS 中被称为 Functional Notation),在 CSS3 中被赋予了更多的黑科技,不过鉴于没有浏览器实现,就仅附上 W3C 标准(英文)MDN参考文档,剩下的有空再谈(又给自己挖坑…

counter[s]

content 属性里面非常有趣的的一位就是它了,华丽丽的计数器。有序列表ol下的每一个li元素都会默认有数字编号,而 counter 则可以完成更加复杂的嵌套列表的序号。

不过 counter 用起来也挺麻烦的,首先要重置计数器:为父元素的样式添加counter-reset属性,属性值为计数器的名字。然后在需要显示计数数值的元素的伪元素上,添加counter-increment: counter-name的属性,并把content属性写为counter(counter-name)就可以了。

counter-increment这个属性在默认情况下,是让计数器自增1,但也可以这样同时创建多个计数器,并赋予不同的自增减值:

1
2
/* 名为 my-counter 的计数器每次计数时,自增2;名为 your-counter 的计数器每次计数时,自增1;名为 his-counter 的计数器每次计数时,自减1。 */
counter-increment: my-counter 2 your-counter his-counter -1;

而关于counters和嵌套的计数器,MDN 的这个 Demo已经讲得非常清楚了,我就不多说了…

关于计数所显示的“数字”,默认情况下是阿拉伯数字,可以将counter(counter-name,style)counters(counter-name,string,style)中的 style 换成list-style-type所允许的任意值,只是在 counters 中,修改一个 style,所有的字符都会跟着变…可以看一下这个 Demo

PS,display:none的元素不会增加计数,而visibility:hidden的元素可以,这个跟displayvisibility这两个属性本身的特性有关啦。


CSS 作为一系列标准的集合也在不断更新和完善,当初标准的制定者大概怎么也没想到,伪元素居然被用在了那么多猎奇的地方上,而现在以我的目光来看,那些原本的用途反而变成了猎奇的存在 XD

本部落格采用DISQUS评论系统,如果您无法见到留言框,可前往我的GitHub微博提Issue(留言)。
为您带来了不便我也很尴尬╮(╯_╰)╭