dl是语义容器,不适合视觉自定义列表。推荐使用ul配合::marker伪元素设置content属性,或ol配合CSS计数器实现嵌套编号,以分离语义与样式。注意需设置aria-hidden提升可访问性,同时避免使用background-image导致缩放失真。
HTML文档结构列表标记自定义教程
作者:技术拾光
时间:2026-07-27
浏览:236
文章目录
在前端日常开发中,若要实现“自定义列表”的视觉效果,开发者往往会首先想到 dl、dt、dd 这一套组合。但实际使用中存在诸多问题,不应采用这种方式。

为什么不能用 dl 实现“自定义列表”视觉效果
dl 并非视觉容器,而是一个语义容器,其职责是表达“术语–解释”的映射关系。浏览器、搜索引擎和读屏软件均严格按照此逻辑解析:每个 dt 必须包含内容,对应的 dd 必须紧随其后,且不能脱离上下文独立存在。
在实际使用中容易出现以下问题:
- 将
dl当作带缩进的ul来使用,屏幕阅读器会误读为“术语:苹果”,停顿后再读“解释:一种水果”,导致信息交互错乱。 - 为
dt设置list-style-type: none无效,该属性在dt和dd上默认不生效。 - 试图使用
start或type属性控制编号,但这些属性不在dl的规范中。
ul + ::marker 是最简可靠的自定义符号方案
目前主流浏览器(Chrome 89+、Firefox 68+、Safari 15.4+)已原生支持 ::marker 伪元素。该伪元素专门用于替换列表项前缀,语义清晰、可访问性好,且无需额外增加 DOM 节点。
实现方法如下:
- 使用
list-style: none清除默认符号。 - 为
li::marker设置content属性,支持字符串、emoji 甚至计数器(如counter(list-item, lower-roman))。 - 若需使用图标,优先选择内联 SVG 或字体图标(例如
content: "→"; font-family: "iconfont"),避免使用background-image,防止缩放时失真。 - 注意:
::marker无法设置宽高或背景色,但可通过color和font-size控制颜色与大小。
示例——绿色箭头加缩进对齐:
ul.custom {
list-style: none;
}
ul.custom li::marker {
content: "→";
color: #28a745;
font-size: 1.1em;
}
ul.custom li {
padding-left: 0.5em;
}
需要复杂编号时,使用 ol + CSS 计数器比修改 HTML 更可控
例如实现“Step 1.1”“Step 1.2”等嵌套编号,若硬编码 value 属性或依赖 JavaScript 动态生成,不仅难以维护,还会破坏语义结构。CSS 计数器是标准解决方案。
关键要点:
- 在
ol上使用counter-reset初始化计数器(例如counter-reset: step 0)。 - 在
li上使用counter-increment递增值(例如counter-increment: step)。 - 在
content中使用counter(step)或counters(step, ".")输出层级编号。 - 嵌套多个
ol时,外层和内层的counter-reset必须不同名,否则会互相覆盖。
常见问题:忘记为 li::before 设置 display: inline-block,导致编号和文字换行后错位,需要排查。
图标型前缀慎用 background-image,优先考虑 ::before + 字体图标
background-image 方案看似简单,实际使用中存在以下问题:
- 图片尺寸固定,响应式缩放时容易模糊或裁切。
- 无法继承父级颜色,换色需重新切图。
- 加载失败时留下空白区域,无 fallback 文本。
更稳妥的做法:
- 使用
li::before配合字体图标(如 Font Awesome、Iconfont),通过content: "f054"插入。 - 设置
font-size和color统一控制尺寸和配色。 - 添加
margin-right: 0.5em确保图标与文字间距稳定。 - 为图标添加
aria-hidden="true",避免读屏软件重复朗读。
实际上,真正需要“自定义”的并非标签本身,而是在不破坏语义的前提下,使视觉表达精准匹配信息层级——这一边界比看起来更加狭窄。
实用工具推荐
电子包浆
使用 ›绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
图片压缩
使用 ›选择画质和输出格式,预览压缩前后的大小。