先记住这个答案
当内容是一组并列的、顺序无关的条目时,应使用 ul 加 li,而不是用 p 或 div 拼接。判断方法很直接:把条目顺序打乱,如果含义不变,就用 ul;如果含义改变,用 ol。语义价值在于:ul 的隐含 ARIA 角色是 list,li 是 listitem,屏幕阅读器会播报列表包含多少项、当前是第几项,用户还能用快捷键在列表间跳转。用 div 模拟则丢失这一切,只剩视觉项目符号。
- 顺序无关的一组并列项才用 ul
- li 语义让屏幕阅读器播报项数和位置
- div 模拟列表只剩视觉符号,丢失语义
- 顺序打乱含义变了就改用 ol
列表语义如何被解析与播报
ul 在 HTML 规范中表示一组顺序无关的条目集合,其隐含 ARIA 角色为 list,li 的隐含角色为 listitem。浏览器构建可访问性树时保留这些角色和项数信息,因此屏幕阅读器进入列表时会播报类似列表、共五项,随后按项导航时播报第二项,共五项。这是 p 与 div 都不具备的机制:p 的角色是 paragraph,div 无角色,辅助技术无法得知它们构成集合。
选择 ul 还是 ol 的标准测试是重排:把条目顺序打乱,含义不变则用 ul,含义变了(如操作步骤、排行榜)则用 ol。项目符号的样式属于表现层,HTML 早期提供的 type 属性已废弃,应改用 CSS 的 list-style-type;嵌套层级下的符号由用户代理或 CSS 决定,与语义无关。这一分离保证改样式不破坏语义。
电商筛选已选条件列表的实现
某电商结果页顶部展示已选筛选条件:品牌 A、价格区间、可分期,共三项,可点击移除。它们来自用户任意顺序的勾选,顺序无意义。约束是必须支持键盘和读屏用户。决策是用 ul 包裹三个 li,每个 li 内放移除按钮,而不是拼接三个 div 加圆点。结果:读屏播报已选条件,列表,三项,用户在列表跳转快捷键下能整体跳过或逐项定位。
之所以这样处理,是因为 div 方案需要额外加 role 为 list 与 listitem 才能达到同等播报,还容易被后续维护者删掉。原生 ul 零成本提供语义,且 CSS 可用 list-style 为 none 去掉圆点而不影响可访问性。视觉上可以做成横排标签样式,但语义层仍是列表,两种呈现互不冲突。
不该用 ul 的常见失效情形
第一类失效:内容是有因果或时间顺序的步骤,如下载、解压、安装。打乱顺序含义改变,此时必须用 ol 而非 ul,否则读屏用户听不到步骤序号,操作者可能按错误顺序执行。第二类失效:单段连续叙述文本被拆成多个 li 只为获得缩进,这会让读屏把一篇文章切成碎片式列表,语义反而失真。
第三类:把 ul 当纯布局容器,比如用它排列卡片网格但卡片之间并无并列集合关系(如一张头图加一段简介)。更合适的是 section 或 article 分组。若仅为缩进或圆点样式使用 ul,代价是引入虚假语义;正确的做法是用普通容器加 CSS margin,表现与语义各归其位,ul 的合法子元素也应限定为 li、script、template。
容易答错的地方
- 有圆点就该用 ul
- 圆点只是默认样式,可用 list-style 去除。判断依据是内容是否为顺序无关的集合,而非视觉效果;为圆点样式而加 ul 会引入虚假列表语义。
- div 加 CSS 圆点等于 ul
- div 无角色,屏幕阅读器不播报项数和位置,也无法用列表快捷键导航。要补偿需手动加 role 为 list 和 listitem,成本更高且易丢失,原生元素更可靠。
面试官还会怎么问?
ul 的 type 属性还能用吗
不建议。type 属性已废弃,子弹样式属于表现层,应用 CSS 的 list-style-type(如 disc、circle、square)控制。嵌套层级未指定时由用户代理按层级选择符号,语义不受影响。
ul 和 ol 如何快速选择
做重排测试:把条目顺序打乱,含义不变用 ul,含义改变用 ol。例如菜谱步骤换序会出错用 ol,而购物清单换序无所谓用 ul。这是规范给出的直接判据。
ul 里可以直接放 div 吗
规范上 ul 允许的内容只有 li、script 和 template。直接放 div 属于无效嵌套,校验器会报错,可访问性树也可能不符合预期。需要包裹内容时应把 div 放在 li 内部。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。