这篇文章来自我们的特约作者——孟智强 同学,他之前的用CSS画一个冰墩墩的文章就广受称赞,来看看这里他分享的用CSS实现有序列表标号的知识
前言
内网某平台在页面首次打开时会弹一个框,其中包含一个带有编号的列表结构,好奇扒了下代码,发现列表的编号是放在 ul > li
标签下的 span
标签中的,这些数字编号应该是通过该平台的框架模板生成的,然后再利用 CSS 进行装饰,使其呈现带圈序号的样子。(见下图)
看到这里我可就不困了,一心想着能否通过 CSS 直接生成类似于上述编号的效果,从而省略掉 span
标签呢?
ol 标签
在前端开发中,提到编号必然会想到 ol
这个熟知的 HTML 标签,该标签表示一个带有编号的列表,缺省情况下自带阿拉伯数字编号(在编写业务 CSS 代码时,通常会重置该特性)。
例如下面的 HTML 代码:
<ol>
<li>沉淀内心:每天抽出一定的时间来冥想、冥思、反省自己,让内心变得更加平静和深沉。</li>
<li>培养兴趣:多尝试新事物,学习新技能,参与各种有意义的活动,让自己的兴趣爱好得到满足和提升。</li>
<li>学会感恩:感激生命中的每一个美好瞬间和每个给予我们温暖、帮助和支持的人。</li>
<li>保持谦虚:要时刻保持自我反省和谦虚的态度,学会接受批评,不断反省自己的不足之处,并努力改正。</li>
<li>多一份善意:尽可能多地给予别人帮助和关爱,让身边的人感到温暖和幸福。</li>
</ol>
默认情况下会渲染为带有 1、2、3 这类序号的列表:
不过很明显,这并不是我们想要的带圈数字的效果。我们接着往下看。
list-style-type
ol
或 ul
标签的列表符号类型可通过 list-style-type
这个 CSS 属性来控制,该属性支持的值非常多,属性值渲染效果截图示意:
然而,这其中并没有我们所需的带圈数字这种类型的效果,但我们同时也发现了一个有意思的点,那就是 list-style-type
的属性值支持自定义字符串(上图中最后一个示例)。换言之,若我们依次将 ①②③ 这类字符赋值给列表项的 list-style-type
属性,不就可以生成带圈数字的编号效果了吗?眼见为实:
<ol class="list">
<li>沉淀内心:每天抽出一定的时间来冥想、冥思、反省自己,让内心变得更加平静和深沉。</li>
<li>培养兴趣:多尝试新事物,学习新技能,参与各种有意义的活动,让自己的兴趣爱好得到满足和提升。</li>
<li>学会感恩:感激生命中的每一个美好瞬间和每个给予我们温暖、帮助和支持的人。</li>
<li>保持谦虚:要时刻保持自我反省和谦虚的态度,学会接受批评,不断反省自己的不足之处,并努力改正。</li>
<li>多一份善意:尽可能多地给予别人帮助和关爱,让身边的人感到温暖和幸福。</li>
</ol>
.list > li:nth-child(1) {list-style-type: '① ';}
.list > li:nth-child(2) {list-style-type: '② ';}
.list > li:nth-child(3) {list-style-type: '③ ';}
.list > li:nth-child(4) {list-style-type: '④ ';}
.list > li:nth-child(5) {list-style-type: '⑤ ';}
效果如下:
这个效果已经非常接近预期目标了,美中不足的是实现的 CSS 代码太过无脑,一点都不优雅!
@couter-style
在 CSS3 新规范中,list-style-type
还支持使用 @counter-style
规则自定义的符号列表。@counter-style
规则非常强大,允许开发者自定义他们自己的列表符号样式,可以实现几乎任何项目符号的效果。文档传送门
回到我们的需求,换成 @counter-style
实现的话只需寥寥几行,非常地优雅:
@counter-style circled-num {
system: fixed;
symbols: ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩; /* 注意要用空格隔开,无需引号 */
suffix: ' ';
}
.list {list-style: circled-num;}
效果如下:
再来个 emoji 字符的例子:
@counter-style emoji-clock {
system: fixed;
symbols: 🕐 🕑 🕒 🕓 🕔 🕕 🕖 🕗 🕘 🕙;
suffix: ' ';
}
.list {list-style: emoji-clock;}
注意:Safari 浏览器目前还不支持
@couter-style
。
伪元素 + CSS计数器
像列表符号这种装饰性质的任务,利用伪元素来呈现也是个不错的方法,至于实现数字编号可以利用 CSS 计数器来生成。
先说下伪元素,CSS 伪元素规范第4版新出了一个 ::marker
,它作用在任何类型为 list-item 的元素上,例如在常见的 <li>
标签中就能一瞥它的身影:
利用 ::marker
伪元素可以改变列表符号的颜色、字号、字体、甚至内容,但仅限于此,它并不支持诸如 width
、margin
、border
等盒模型属性,所以可定制性方面大打折扣,最终还得是 ::before
或 ::after
出场。
再来说下 CSS 计数器,它是由 CSS 内部维护的变量,这些变量可根据定义的规则来递增或递减,利用 CSS 计数器可以自动为网页中的标题编号,或更改有序列表的编号。文档传送门
通过将伪元素和 CSS 计数器相结合,我们可以非常灵活且优雅地实现预期的目标。CSS 代码如下:
.list {
list-style: none; /* 移除缺省的列表编号 */
counter-reset: order; /* 初始化一个名为 order 的计数器 */
}
.list > li::before {
content: counter(order); /* 显示计数器当前的值 */
counter-increment: order; /* 递增计数器(缺省增量为1) */
/* 下面是装饰类代码(略) */
border: 1px solid #575D6C;
border-radius: 50%;
...
}
最终效果如下:
总结
list-style-type
CSS 属性提供了大量常见的列表符号,可满足普通列表编号的需求。list-style-type
支持自定义字符串,无序列表自定义符号的场景会用得上。- 使用
::marker
伪元素可以对列表符号进行简单的定制。 @couter-style
提供更高级的编号类型定制。- 对于高度定制化的列表编号场景,可使用
::before/::after
伪元素结合 CSS 计数器来实现。