使用 CSS 创意样式化列表的方法
浏览器默认的列表样式很少能匹配真实的设计需求。无论你是在构建导航菜单、分步教程,还是产品功能列表,CSS 列表样式都能为你提供工具,让它们看起来更有设计感。本文涵盖了最实用、基于标准的技术——从原生列表属性到 CSS 计数器和自定义标记——同时不牺牲可访问性。
核心要点
- 在应用任何 CSS 之前,选择正确的语义化 HTML 列表元素(
<ul>、<ol>或<dl>),因为屏幕阅读器依赖这种结构。 - 使用
::marker进行简单的标记颜色和字体更改,当需要完全控制自定义项目符号的布局时,使用::before配合 flexbox。 - CSS 计数器允许你创建自定义的编号格式,包括使用
counters()实现多级层次编号。 - 当在有意义的列表上使用
list-style: none时,考虑添加role="list",特别是为了在 Safari/VoiceOver 中保留列表语义。
从正确的 HTML 列表类型开始
在使用 CSS 之前,先选择正确的元素:
<ul>— 无序列表,顺序不重要(导航菜单、功能列表)<ol>— 有序列表,顺序有意义(说明、排名)<dl>— 描述列表,将术语与定义配对(词汇表、元数据)
语义化 HTML 在这里很重要。屏幕阅读器会宣告列表类型和项目数量,这有助于用户在阅读单个项目之前理解上下文。
list-style-* 属性:你的起点
list-style 简写属性包含三个属性:
ul {
list-style: square inside none;
/* list-style-type | list-style-position | list-style-image */
}
list-style-position 值得清楚理解:
outside(默认)— 标记位于外边距中,文本保持整齐对齐inside— 标记与文本一起流动,导致多行项目换行
list-style-image 虽然存在但功能有限——你无法调整图像大小或重新定位。对于自定义图像项目符号,使用带有 background-image 的 ::before 伪元素可以提供更多控制。
使用 CSS ::marker 样式化原生标记
::marker 伪元素允许你直接样式化内置的项目符号或数字——无需额外的标记:
li::marker {
color: deeppink;
font-size: 1.2em;
font-weight: bold;
}
重要限制: ::marker 仅支持特定的 CSS 属性子集:color、content、font-*、direction、unicode-bidi、white-space、text-combine-upright 以及动画/过渡属性。你不能应用 display、background、padding、margin 或定位。将其视为文本级样式钩子,而不是完整元素。
::marker 在当前浏览器中的支持良好,但请检查你的目标浏览器矩阵。对于简单的颜色或字体更改,它通常是最简洁的选项。
使用 ::before 自定义列表项目符号
当 ::marker 不够用时——对于图标样式的项目符号、复杂对齐或过渡效果——改用 ::before:
ul {
list-style: none;
padding-left: 0;
}
ul li {
display: flex;
align-items: flex-start;
gap: 0.5rem;
}
ul li::before {
content: "✓";
color: green;
flex-shrink: 0;
}
可访问性注意事项: 设置
list-style: none可能导致 Safari/VoiceOver 停止将元素识别为列表。如果列表语义有意义,请在<ul>或<ol>上添加role="list"。
Discover how at OpenReplay.com.
用于样式化有序列表的 CSS 计数器
CSS 计数器让你完全控制编号列表的格式——对于带有自定义前缀、后缀或多级编号的样式化有序列表很有用:
ol {
list-style: none;
counter-reset: steps;
}
ol li {
counter-increment: steps;
}
ol li::before {
content: "Step " counter(steps) ". ";
font-weight: bold;
color: #333;
}
嵌套计数器
对于嵌套列表,counters()(复数)输出完整的层次结构:
ol {
list-style: none;
counter-reset: steps;
}
ol li {
counter-increment: steps;
}
ol li::before {
content: counters(steps, ".") " ";
}
/* 输出: 1, 1.1, 1.2, 2, 2.1 */
counter-increment 属性还接受步长:counter-increment: steps 2 每次递增 2。
关于 @counter-style 的说明
@counter-style at 规则允许你定义完全自定义的计数系统——自定义符号、字母表或循环模式:
@counter-style thumbs {
system: cyclic;
symbols: "👍" "👎";
suffix: " ";
}
ul {
list-style-type: thumbs;
}
谨慎使用。 @counter-style 的浏览器支持仍不完整——值得注意的是,Safari 仅在版本 17 中添加了支持。始终在目标浏览器中进行测试,并在同一元素上定义 list-style-type 回退,以确保优雅降级。
选择正确的方法
| 目标 | 最佳技术 |
|---|---|
| 更改标记颜色或字体 | ::marker |
| 自定义图标或复杂对齐 | ::before 配合 flexbox |
| 自定义编号格式 | CSS 计数器配合 ::before |
| 自定义计数系统 | @counter-style(带回退) |
结论
良好的 CSS 列表样式始于语义化 HTML,并在其之上叠加视觉改进。使用 ::marker 进行轻量级的颜色和字体更改,当需要布局控制时使用 ::before,当有序列表需要自定义编号时使用 CSS 计数器。避免在不通过 ARIA 恢复列表语义的情况下移除列表语义。每种技术都有明确的用例——选择适合你设计的技术,不要过度复杂化。
常见问题
技术上可以,但通常你会选择一种标记策略。如果你使用 list-style: none 移除原生标记,则使用 ::before 作为自定义项目符号。如果保留原生标记,则使用 ::marker 进行简单的颜色和字体调整。
Safari 的可访问性启发式将 list-style: none 解释为该元素用于布局而非语义列表的信号。这导致 VoiceOver 停止将其宣告为列表。在 ul 或 ol 元素上添加 role='list' 可以明确恢复列表语义,使辅助技术继续报告正确的结构和项目数量。
可以。CSS 计数器不限于列表元素。你可以将 counter-reset 和 counter-increment 应用于任何元素,如 div、标题或 section,并使用伪元素上的 content 属性显示计数器值。这使它们对于编号章节、图表或任何重复内容模式都很有用。
将 ul 设置为 display: flex,并使用 list-style: none 和 padding-left: 0 移除默认列表样式。然后将每个 li 或其锚点样式化为内联 flex 项目,使用 gap 或 margin 设置适当的间距。如果希望屏幕阅读器在 Safari 中仍将其宣告为导航列表,请记得在 ul 上添加 role='list'。
Truly understand users experience
See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..