分页组件可访问性需兼顾语义结构、焦点管理与屏幕阅读器播报:当前页用aria-current="page"标注在含合法href的上;上/下一页用并正确禁用;整体包裹,页码用,省略号须为真实文本节点。

分页组件的可访问性不是“加几个属性就完事”,而是从语义结构、焦点管理、屏幕阅读器播报三个层面同步设计。核心原则:当前页必须被明确识别,禁用状态不能靠视觉欺骗,所有交互必须键盘可达。
aria-current="page" 必须加在 @#@#@#@#@#@#@#@#@#@0。即使用户点它不会跳转(JS 拦截),href 也必须指向一个合法 URL,否则键盘用户无法聚焦、无法按空格/回车触发,辅助技术也无法定位上下文。
常见错误:
- 给当前页加
disabled属性(<a disabled></a>不合法) - 用
<span></span>或<button></button>替代<a></a>,仅靠 CSS 样式标亮 -
href="#"或javascript:void(0)—— 这些值不构成有效导航目标,aria-current失效
上一页/下一页按钮必须用 <button type="button"></button>,禁用时设 disabled + aria-disabled="true"
它们不是导航链接,而是页面内交互控件,所以不用 <a></a>。但必须支持键盘操作:可聚焦、空格/回车触发、禁用时不可聚焦也不可操作。
禁用逻辑不能只靠 class 切换或 CSS 灰色:
- 当前页为 1 →
prev按钮必须有disabled属性,并同步加aria-disabled="true"和tabindex="-1" - 当前页为总页数 →
next同理 - 绑定的 click 回调里,第一行就应是
if (this.disabled) return,避免逻辑穿透
别写 <button onclick="goPrev()">上一页</button> 而不控制状态——这会让键盘用户在首页仍能按空格,触发无效行为。
分页容器必须用 <nav></nav> 包裹,并配 aria-label
<nav></nav> 是语义必需,不是装饰。它告诉辅助技术:“这是一个独立的导航区域”。但不能滥用:role="navigation" 显式写在 <nav></nav> 上属于冗余,可能覆盖浏览器默认行为。
aria-label 必须存在,且内容要具体:
- ✅
<nav aria-label="搜索结果分页"></nav> - ❌
<nav aria-label="分页"></nav>(太泛,无上下文) - ❌ 仅靠视觉文字“第 1 页,共 12 页”而不设
aria-label(屏幕阅读器看不到)
嵌入式分页(如弹窗表格内)不加 <nav></nav>,改用 <div role="region" aria-label="表格分页">,避免干扰主导航流。
<h3>页码列表必须用 <code><ol></ol>,省略号必须是真实文本节点
页码是有序序列,<ol></ol> 比 <ul></ul> 更准确。每个页码项用 <li>,当前页项加 aria-current="page"。
省略号 … 必须是 DOM 中的真实文本节点,不能靠 CSS ::before 伪元素生成——读屏软件会跳过伪元素内容,导致“1 2 … 8 9”被读成“1 2 8 9”,中间断层。
动态渲染时别用 innerHTML 拼接整个列表:
- 有 XSS 风险(尤其搜索结果含用户输入)
- 每次重绘丢失焦点、事件监听和自定义属性
- 推荐用
document.createElement+appendChild或DocumentFragment批量插入
最易被忽略的一点:多个分页组件共用同一套状态变量(比如全局 currentPage),会导致翻页互相污染。每个实例必须隔离状态,哪怕只是用闭包或组件级 this.currentPage。











