CSS 计数器详解与巧用
1. CSS 计数器简介
1.1 什么是CSS计数器
计数器本质上是由 CSS 维护的变量,根据规则安装使用次数递增变量或者递减以达到计数的目的,其中按照递减规律计数的计数器称作反向计数器。使用<ol>
元素创建的有序列表隐含地具有一个名为 list-item
的计数器,例如:
<ol> <li>第一项</li> <li>第二项</li> <li>第三项</li> </ol>
其效果如下:
- 第一项
- 第二项
- 第三项
可以看到,虽然我们没有为<ol>
列表项编号,但是其显示出来的效果为我们实现了自动计数编号,随着列表项递增,序号递增。
1.2 CSS计数器样式
CSS 计数器引入了@counter-style
规则,它允许开发者自定义计数器的样式,以便与 CSS 列表标记和生成内容计数器一起使用,即在list-style-type
属性或counter()
和counters()
函数中使用这些样式。计数器样式定义了如何将计数器值转换为字符串。计数器样式(Counter styles)由名字、算法、负号、前缀、后缀、范围、口语形式、后备样式组成。
例如:
<ul class="at"> <li>第一项</li> <li>第二项</li> <li>第三项</li> </ul> <style> ul.at { list-style: at; } @counter-style at { system: cyclic; symbols: '@'; suffix: " "; } </style>
其效果如下:
2 @counter-style
规则详解
2.1 @counter-style
的语法格式
在 1.2 CSS计数器样式 的例子中,已经初步展示过 @counter-style
的用法,该规则的作用是定义自定义计数器样式,即定义如何把一个计数器的值
转化为字符串
表示。其语法结构为:
@counter-style <counter-style-name> { <declaration-list> }
其中:
<counter-style-name>
用于标识该计数器样式的名称,我们在定义好样式后,就是通过该名称来这个样式的。< counter-style-name >
可以是CSS关键字decimal
、disc
、square
、circle
、disclosure-open
和disclosure-closed
等等,实际上这些关键字是系统预定义好了的样式,你也可以自己通过@counter-style
关键字 | 描述 |
decimal |
表示十进制阿拉伯数字。 |
disc |
表示实心圆。 |
square |
表示实心正方形。 |
circle |
表示空心圆。 |
disclosure-open 和 disclosure-closed |
表示适用于指示打开 或关闭 的公开小部件的符号。 |
<declaration-list>
表示声明列表,可以对以下属性进行声明:
属性 | 类型 |
system |
<counter system> |
symbols |
<counter symbols> |
additive-symbols |
<additive-symbols> |
negative |
<negative symbol> |
prefix |
<prefix> |
suffix |
<suffix> |
range |
<range> |
pad |
<padding> |
speak-as |
<speak-as> |
fallback |
<counter-style-name> |
- 关于声明列表的具体内容请见2.3 计数器样式声明小节。
2.2 内置计数器样式名
CSS规范中定义了很多内置样式,我们只要使用这些样式名关键字就可以直接使用相应的CSS计数器样式。这一小节,我们介绍部分最常见的内置样式名关键字以及其是如何预定义的。对于其他没有提到的内置计数器样式名关键字,读者可以查看相应的W3C中的CSS文档。
(1) disc
表示实心圆,类似于 • U+2022 BULLET。该预定义样式的规范定义为:
@counter-style disc { system: cyclic; symbols: \2022; /* • */ suffix: " "; }
例如:
<ul class="disc"><li>disc</li></ul>
其效果如下:
- disc
(2) circle
表示实心圆,类似于 • U+2022 BULLET。该预定义样式的规范定义为:
@counter-style circle { system: cyclic; symbols: \25E6; /* ◦ */ suffix: " "; }
例如:
<ul class="circle"><li>circle</li></ul>
其效果如下:
- circle
(3) square
表示实心正方形,类似于 ▪ U+25AA BLACK SMALL SQUARE。该预定义样式的规范定义为:
@counter-style square { system: cyclic; symbols: \25AA; /* ▪ */ suffix: " "; }
例如:
<ul class="square"><li>square</li></ul>
其效果如下:
- square
(4) decimal
表示十进制阿拉伯数字(例如,1,2,3,…, 98, 99, 100)。该预定义样式的规范定义为:
@counter-style decimal { system: numeric; symbols: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9'; }
例如:
<ol class="decimal"> <li>decimal</li> <li>decimal</li> <li>decimal</li> <li>...</li> </ol>
其效果如下:
- decimal
- decimal
- decimal
- ...
(5) decimal-leading-zero
用起始零填充的十进制数 (e.g., 01, 02, 03, …, 98, 99, 100).
@counter-style decimal-leading-zero { system: extends decimal; pad: 2 '0'; }
例如:
<ol class="decimal-leading-zero"> <li>decimal-leading-zero</li> <li>decimal-leading-zero</li> <li>decimal-leading-zero</li> <li>...</li> </ol> <style> ol.decimal-leading-zero { list-style: decimal-leading-zero} </style>
其效果如下:
(6) trad-chinese-informal
繁体中文非正式编号 (e.g., 一千一百一十一)。
例如:
<ol class="trad-chinese-informal"> <li>trad-chinese-informal</li> <li>trad-chinese-informal</li> <li>trad-chinese-informal</li> <li>...</li> </ol> <style> ol.trad-chinese-informal { list-style: trad-chinese-informal;} </style>
其效果如下:
(7) lower-roman
小写ASCII罗马数字 (e.g., i, ii, iii, …, xcviii, xcix, c),该值值预定义样式的规范定义为:
@counter-style lower-roman { system: additive; range: 1 3999; additive-symbols: 1000 m, 900 cm, 500 d, 400 cd, 100 c, 90 xc, 50 l, 40 xl, 10 x, 9 ix, 5 v, 4 iv, 1 i; }
(8) upper-roman
大写ASCII罗马数字 (e.g., I, II, III, …, XCVIII, XCIX, C),该值值预定义样式的规范定义为:
@counter-style upper-roman { system: additive; range: 1 3999; additive-symbols: 1000 M, 900 CM, 500 D, 400 CD, 100 C, 90 XC, 50 L, 40 XL, 10 X, 9 IX, 5 V, 4 IV, 1 I; }
(9) lower-greek
小写古典希腊语 (e.g., α, β, γ, …, ω, αα, αβ),该值值预定义样式的规范定义为:
@counter-style lower-greek { system: alphabetic; symbols: "\3B1" "\3B2" "\3B3" "\3B4" "\3B5" "\3B6" "\3B7" "\3B8" "\3B9" "\3BA" "\3BB" "\3BC" "\3BD" "\3BE" "\3BF" "\3C0" "\3C1" "\3C3" "\3C4" "\3C5" "\3C6" "\3C7" "\3C8" "\3C9"; /* α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ σ τ υ φ χ ψ ω */ }
(10) upper-latin
大写ASCII字母 (e.g., A, B, C, …, Z, AA, AB),该值值预定义样式的规范定义为:
@counter-style upper-latin { system: extends upper-alpha; }
(11) disclosure-open
和 disclosure-closed
表示适用于指示 打开
或 关闭
的公开小部件的符号,如HTML <details>
元素。这两个值预定义样式的规范定义为:
@counter-style disclosure-open { system: cyclic; suffix: " "; /* for symbols, see normative text below */ }
@counter-style disclosure-closed { system: cyclic; suffix: " "; /* for symbols, see normative text below */ }
例如:
<ul class="disclosure-open"><li>disclosure-open</li></ul> <ul class="disclosure-closed"><li>disclosure-closed</li></ul> <style> ul.disclosure-open { list-style: disclosure-open} ul.disclosure-closed { list-style: disclosure-closed} </style>
其效果如下:
2.3 计数器样式声明描述符
在计数器样式的声明列表中可以使用以下值进行声明:
描述符 | 描述 |
system |
指定一个算法,用于将计数器的整数值转化为字符串表示。 |
symbols |
定义一个符号,用于标记的表示。符号可以包含字符串,图片或自定义的识别码。 |
negative |
指定一个符号,当计数器表示的值为负的时候,把这个符号加在值的前面或后面 |
prefix |
指定一个符号,加在标记表示符的前面。前缀在最后阶段才会被加上,所以在计数器的最终表示中,它在negative (en-US)前。 |
suffix |
与prefix类似,suffix指定一个符号,加在标记表示符的后面。 |
range |
指定一个counter-style 生效的范围,如果计数器的值不再这个范围内,那么自定义的counter-style 不会生效,counter-style 会后退到 fallback 的样式。 |
pad |
在你想要给标记表示符最小值时使用。比如说,你想要计数器从01开始,经过02,03,04,那么这时可以使用pad 了。对于大于pad指定值的表示符,标记会恢复为normal 。 |
fallback |
定义一个备用的系统,当自定义的系统不能使用或者计数器的值超过了定义的范围时使用。如果备用系统也不能表示计数器的值,那么备用系统的备用系统(如果有的话)将会启用。如果没有指定备用系统,或者备用系统链不能够正确表示一个值,那么最终会降为十进制样式表示。 |
additive-symbols |
尽管symbols属性中指定的符号可以被system 中定义的大部分算法所使用,但是一些system 属性的值,比如additive ,依赖于本描述符所描述的加性元组。 |
speak-as |
定义如何在语音识别器中读出计数器样式,比如屏幕阅读器。例如基于该描述符的值,标记符号的值可以作为有序列表的数字或者字幕作为无序列表的音频提示读出。 |
2.3.1 system
解析
指定一个算法,用于将计数器的整数值转化为字符串表示。其值及其描述如下:
值 | 描述 |
cyclic |
表示循环浏览提供的符号列表。一旦到达符号列表的末尾,它将循环回到开头并重新开始。该系统对于只有一个符号的简单项目符号样式或具有多个符号的样式很有用。描述符中必须至少指定一个符号symbols ,否则计数器样式无效。 |
numeric |
将计数器符号解释为位值编号系统中的数字。数字系统类似于上述alphabetic系统。主要区别在于,在alphabetic系统中,描述符中给出的第一个计数器符号symbols 被解释为1,下一个被解释为 ,2依此类推。但是,在数字系统中,第一个计数器符号被解释为 0,下一个被解释为1,然后2是 ,依此类推。描述符中必须至少指定两个计数器符号, symbols 否则计数器样式无效。 |
alphabetic |
将指定的符号解释为数字,以字母编号系统。如果字符"a"to"z"被指定为计数器样式中的符号alphabetic,那么系统的前 26 个计数器表示将是"a",“b"最多"z”. 至此,行为与上述symbolic 系统的行为相同。但是,在 之后"z",它将继续为"aa", “ab”, “ac”…描述 symbols 符必须至少包含两个符号,否则计数器样式无效。描述符中提供的第一个计数器符号symbols 被解释为1,下一个被解释为 ,2依此类推。该系统也严格定义为正计数器值。 |
symbolic |
循环浏览提供的符号列表。在每个连续的循环中,用于计数器表示的符号加倍、加倍,等等。例如,如果提供的原始符号是“◽”和“◾”,则在每次连续通过时,它们将变为“◽◽”和“◾◾”、“◽◽◽”和“◾◾◾”等。描述符中必须至少指定一个符号,symbols否则计数器样式无效。此计数器系统仅适用于正计数器值。 |
additive |
用于表示“符号-值”编号系统,例如罗马数字,它不是重复使用不同位置的数字来获得不同的值,而是为更大的值定义额外的数字。可以通过添加数字中的数字来找出此类系统中数字的值。 additive-symbols必须使用至少一个加法元组指定额外的描述符,否则计数器样式规则将无效。加法元组类似于复合计数器符号,由两部分组成:普通计数器符号和非负整数权重。加法元组必须按其权重的降序指定,否则系统无效。 |
fixed |
定义了一组有限的符号被指定。一旦系统遍历了所有指定的符号,它将回退。该系统在计数器值有限的情况下很有用。描述符中必须至少指定一个符号,symbols否则计数器样式无效。也可以在系统之后指定一个可选<integer> 值,作为第一个符号的值。如果省略该整数,则取第一个整数的值作为1 。 |
extends |
允许作者使用另一种计数器样式的算法,但更改其其他方面。如果计数器样式规则正在使用extends 系统,则任何未指定的描述符及其值都将从指定的扩展计数器样式中获取。如果extends 中指定的计数器样式名称不是当前定义的计数器样式名称,它将改为从十进制计数器样式扩展。它不能包含 symbols 或additive-symbols 描述符,否则计数器样式规则无效。如果一个或多个计数器样式定义与它们的扩展值形成一个循环,浏览器会将所有参与的计数器样式视为从十进制样式扩展而来。 |
例子
2.3.2 symbols
解析
定义一个符号,用于标记的表示。符号可以包含字符串,图片或自定义的识别码。这个符号怎样构建标记呢?这依赖于system描述符里面所定义的算法。 举个例子,如果system的值是fixed,那么symbols属性指定的固定的N个符号,将被用来表示计数器的前N个值。用完了前N个符号后,列表里剩下的值将使用fallback定义的样式来表示。
例子
· 表情包列表样式:
<ul> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> </ul> <style scoped lang="scss"> @counter-style meme { system: cyclic; symbols: 😊 😂 🤣 ❤️ 😍 😒 👌 😘 💕 😁 👍 🙌; suffix: " "; } ul { list-style: meme; } </style>
效果如下:
2.3.3 negative
解析
指定一个符号,当计数器表示的值为负的时候,把这个符号加在值的前面或后面
例子
2.3.4 prefix
解析
指定一个符号,加在标记表示符的前面。前缀在最后阶段才会被加上,所以在计数器的最终表示中,它在negative
前。
例子
2.3.5 suffix
解析
与prefix
类似,suffix指定一个符号,加在标记表示符的后面。
例子
2.3.6 range
解析
指定一个counter-style生效的范围,如果计数器的值不再这个范围内,那么自定义的counter-style不会生效,counter-style会后退到fallback
的样式。
例子
2.3.8 pad
解析
在你想要给标记表示符最小值时使用。比如说,你想要计数器从01开始,经过02,03,04,那么这时可以使用pad
了。对于大于pad
指定值的表示符,标记会恢复为normal
。
例子
2.3.9 fallback
解析
定义一个备用的系统,当自定义的系统不能使用或者计数器的值超过了定义的范围时使用。如果备用系统也不能表示计数器的值,那么备用系统的备用系统(如果有的话)将会启用。如果没有指定备用系统,或者备用系统链不能够正确表示一个值,那么最终会降为十进制样式表示。
例子
2.3.10 additive-symbols
解析
尽管symbols属性中指定的符号可以被system中定义的大部分算法所使用,但是一些system属性的值,比如additive,依赖于本描述符所描述的加性元组。Each additive tuple consists of a counter symbol and a non negative integer weight. 每个加性元组包含一个可数的符号和一个非负证书的权重。The additive tuples must be specified in the descending order of their weights.
例子
2.3.11 speak-as
解析
用于定义如何在语音识别器中读出计数器样式,比如屏幕阅读器。例如基于该描述符的值,标记符号的值可以作为有序列表的数字或者字幕作为无序列表的音频提示读出。