Front-End-Checklist 无障碍清单:正确使用列表结构(ul/ol/li)——从 HTML 语义规则到源码级校验实践
Front-End-Checklist 无障碍清单正确使用列表结构ul/ol/li——从 HTML 语义规则到源码级校验实践【免费下载链接】Front-End-Checklist The essential checklist for modern web development, for humans and AI agents项目地址: https://gitcode.com/gh_mirrors/fr/Front-End-Checklist本篇文章以开源仓库 Front-End-Checklist 的 list-structure 技能文档 及其参考实现 为主体系统讲解 Web 开发中最容易被忽视、却直接决定屏幕阅读器信息传达质量的列表结构规则。读完你将掌握ul/ol与li的正确父子关系约束、嵌套列表的规范写法、相关无障碍规则的配套关系以及如何借助仓库内置的 MCP 代码审查工具实现自动化的列表结构检测。列表是网页中最常见的语义结构之一但恰恰因为常见许多开发者会在ul中直接放入div、p甚至裸文本。屏幕阅读器依赖特定的父子关系来播报列表项数量与用户当前所在位置——一旦结构被破坏List of 3 items 会变成乱报、漏报甚至完全失声。Front-End-Checklist 将正确使用列表结构Use correct list structure列为accessibility/document-structure分类下优先级为 medium、难度为 intermediate 的核心规则并在 MCP 工具中提供了对应启发式检测实现。规则一句话定义Lists (ul,ol) should only contain list item elements (li) to ensure they are correctly interpreted by assistive technology.HTML 列表元素ul和ol有一个明确要求它们的唯一直接子元素必须是li以及规范允许的script与template元素。这一点由 HTML Living Standard 的ul/ol元素定义明确写出因此在列表内直接放置div等其他标签会破坏列表语义。原文出处见 list-structure 规则 MDX 文件仓库同时将该规则收录进 rules-catalog 生成目录 与 README 清单。快速参考三条必须遵守的硬性约束技能文档的 Quick Reference 部分给出了可直接照抄的三条规则无序列表ul和有序列表ol中只能包含li元素不要把div、p等其他元素直接放进列表内部嵌套列表也必须包在li元素内部而不能直接嵌在ul/ol的下一层。这三条约束可以浓缩为一句话检查所有列表的 DOM 结构确保ul或ol的直接子元素只有li。为什么列表结构如此重要参考文档 references/rule.md 从四个维度解释了破坏列表结构的后果辅助技术解读屏幕阅读器进入列表时会播报 List of 3 items列表共 3 项。结构不正确会导致列表被数错项数甚至被完全忽略。辅助技术依赖列表容器的存在来播报列表类型bullet list 无序列表 vs numbered list 有序列表和总项数失去容器后这些上下文信息会全部丢失。标记校验破坏列表的父子关系会使 HTML 无效进而引发不可预测的渲染问题XML 类工具在解析时也可能直接失败。一致性用户期望标准的列表行为项目符号、编号这些通过标准标记才能最可靠地实现。搜索引擎解析搜索引擎会利用列表结构理解内容之间的关系结构损坏也会削弱这层信号。规则 MDX 的whyItMatters字段做了更凝练的总结屏幕阅读器依赖列表特定的父子关系才能正确播报项数与当前位置。代码示例错误与正确写法对照参考文档给出了完整的正反例这是审核与修复时的直接依据!-- 错误列表的直接子元素是一个 div -- ul div liItem 1/li liItem 2/li /div /ul !-- 正确所有直接子元素都是 li -- ul liItem 1/li liItem 2/li li !-- 嵌套列表必须放在 li 内部 -- ul liSub-item 1/li /ul /li /ul注意第二个示例中的第三个li嵌套的ul出现在li内部而不是直接作为外层ul的子节点。这是 HTML 规范对嵌套列表的硬性要求——内层列表在语义上属于外层列表项的内容因此必须包裹在li中。修复思路从移除到语义重构SKILL.md 的 Check/Fix/Explain 段落给出了完整的实操流程Check检查检查所有列表的结构确保ul或ol的直接子元素只有li。Fix修复将ul与ol内部的非li元素移除或移到列表之外。Explain解释向团队解释为什么辅助技术需要一致的列表结构来提供准确的导航信息。对照仓库中 listitem 规则当li被用于纯样式目的比如只想画一个项目符号时正确的修法不是硬塞一个列表容器而是换成div或p并用 CSS 实现视觉效果如果li出现在导航中则要保持navulli的完整嵌套链。易混淆的姊妹规则一起审才完整在 Front-End-Checklist 的规则体系中list-structure属于accessibility/document-structure子分类与该分类下的另外三条规则成组出现、常被同时审查关系定义在规则 MDX 的relatedRules字段中规则 slug侧重点与 list-structure 的关系listitem每个li必须有ul/ol/menu作为直接父元素互补list-structure 管列表容器内只能有 lilistitem 管li 不能脱离列表容器definition-listdl术语-定义列表的正确结构同属 document-structure一起审查dlitemdt/dd必须位于dl内同属 document-structure一起审查semantic-lists相关条目组应使用ul/ol/dl而非样式化 div正向规则不仅结构正确还要该用列表时用列表其中 semantic-lists 提供了极好的补充视角许多团队把列表样式用div classfeature-list实现这虽然没有破坏任何父子关系却让屏幕阅读器完全丧失列表上下文。正确做法是使用语义列表元素——ul用于无序项目导航、特性、项目符号ol用于有序序列步骤、排名、指令dl用于术语-定义对术语表、FAQ。另外listitem 规则 还提醒了一个真实场景中的坑当ul上应用list-style: none时部分浏览器如 Safari/VoiceOver 组合会剥离列表语义若这是有意的例如导航菜单应在ul上补充rolelist以恢复列表语义。这也是 ARIA 体系中rolelistitem必须被rolelist拥有的要求在listitem规则里的体现。例外情况与优先级判断规则并非无脑一刀切参考文档的 Exceptions 部分给出了三个重要的判断准则先处理最强语义问题简单的数据表格缺失表头关系带来的问题往往比缺少增强如 caption 或移动端包装更严重应优先修复最强的语义缺陷不要为满足规则而伪造语义不要把纯布局结构硬转成数据表格标记正确的修法可能是彻底移除表格语义重叠问题分层解决多个表格无障碍问题同时存在时先解决表头单元格关系因为下游的播报都依赖它。这三条准则的内核是规则服务于感知、操作、理解评估时应基于渲染后的真实体验而非仅仅静态源码。标准依据规则的来源与权威依据见规则 MDX 的sources字段HTML Living Standardul元素与ol元素primary 权威标准明确规定了唯一直接子元素为li/script/templateMDNul元素参考配套标准还包括W3C WAI WCAG Overview与MDN Accessibility参考文档 Standards 部分并且都强调要对齐实现并验证渲染后的体验而不仅仅是源码。验证方法自动化 手动双通道参考文档的 Verification 部分给出完整的验证路径自动化检查在浏览器无障碍树accessibility tree或无障碍面板中检查相关元素、角色与可访问名称在适用时运行自动化无障碍检查器如axe或Lighthouse。axe DevTools 也列在规则 MDX 的resources字段中作为推荐工具。手动检查使用纯键盘导航测试受影响的 UI确认规则在渲染后的体验中成立如果该规则影响关键交互用屏幕阅读器复测一条有代表性的用户流程。源码级实践MCP 工具如何自动检测列表结构Front-End-Checklist 仓库的 MCP 服务将这条规则落地成了可执行的启发式检测。在 review-code.ts 中可以看到两个方向互补的检测逻辑对应源码第 2269–2296 行检测方向一li的直接父元素必须是合法列表容器// ── list-structure/listitem: li must be direct child of ul or ol for (const li of root.querySelectorAll(li)) { const parent li.parentNode const parentTag parent?.rawTagName?.toLowerCase() if (parentTag parentTag ! ul parentTag ! ol parentTag ! menu) { issues.set(listitem, li element found outside ul, ol, or menu — list items must be direct children of a list container) break } }这段代码遍历所有li一旦发现其直接父元素不是ul/ol/menu三者之一就触发listitem问题——这正是前文 listitem 规则的自动化落地。检测方向二ul/ol的直接子元素必须是li// ── list-structure: ul/ol direct children should be li (not bare text or other elements) for (const list of root.querySelectorAll(ul, ol)) { const badChildren list.childNodes.filter(n { if (n.nodeType 3 /* TEXT_NODE */) return (n.rawText ?? ).trim().length 0 const tag (n as typeof list).rawTagName?.toLowerCase() return tag tag ! li tag ! script tag ! template }) if (badChildren.length 0) { issues.set(list-structure, List element contains direct children that are not li — only li elements should be direct children of ul/ol) break } }注意这段实现与 HTML 规范的完全对齐它把script与template排除在非法直接子元素之外规范允许同时把非空裸文本也判定为违规——这意味着在ul中直接书写文字同样会被标记。这是既管标签、也管文本的完整结构校验也是我们在人工审核时容易遗漏的细节。常见违规模式与修复清单综合规则文档与源码检测逻辑实战中最常遇到的违规模式可以归纳为以下四类违规模式示例正确修法列表容器内直接放divuldivli…/li/div/ul移除div让li直接成为ul子节点列表容器内直接放p或裸文本ulp说明/pli…/li/ul将说明文字移到列表外部li脱离列表容器divliContact us/li/div用ul/ol包裹或按样式需求换成div/p嵌套列表未包在li内ulliA/liulliB/li/ul/ul将内层ul放入外层某个li内部模板化组件如 React 的children透传、CMS 富文本渲染、样式重置中的裸li是最容易产生上述违规的温床审查渲染后的 DOM 时请优先扫描这几类来源。实战落地建议开发阶段把 list-structure 与 listitem 两条规则纳入代码评审 checklist配合 MCP 代码审查工具在提交前完成启发式扫描设计系统层面封装统一的List/ListItem组件如 semantic-lists 规则提供的 React 示例 所示从源头杜绝手写不规范结构若使用list-style: none移除符号样式记得在导航场景补rolelist验证闭环每次修复后走一遍浏览器无障碍面板 → axe/Lighthouse → 屏幕阅读器复测的流程确认渲染后体验而非只盯源码优先级当多个无障碍问题并存时先处理对感知、操作、理解阻塞最严重的语义缺陷不为了凑规则而伪造语义。列表结构是小规则、大影响的典型修复成本往往只需删除一个div或移动一个标签却能直接决定视障用户能否准确获知这个列表有几项、我在第几项。把它纳入自动化检查与人工验证双通道是构建真正无障碍前端的第一步。【免费下载链接】Front-End-Checklist The essential checklist for modern web development, for humans and AI agents项目地址: https://gitcode.com/gh_mirrors/fr/Front-End-Checklist创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →