Back

使用 CSS 创意样式化列表的方法

使用 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 属性子集:colorcontentfont-*directionunicode-bidiwhite-spacetext-combine-upright 以及动画/过渡属性。你不能应用 displaybackgroundpaddingmargin 或定位。将其视为文本级样式钩子,而不是完整元素。

::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"

用于样式化有序列表的 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..

OpenReplay