分页可访问性Pagination Accessibility完整指南ARIA 标记、键盘导航与屏幕阅读器支持【免费下载链接】Front-End-Checklist The essential checklist for modern web development, for humans and AI agents项目地址: https://gitcode.com/gh_mirrors/fr/Front-End-Checklist分页Pagination是现代 Web 应用中最常见的导航组件之一但若标记不当屏幕阅读器用户将无法得知自己当前处于哪一页也难以在分页内容中高效移动。本文以 Front-End-Checklist 仓库中的pagination-accessibility技能文档为主体完整讲解无障碍分页的容器标记、当前页指示、标签规范、键盘可访问性以及页面切换状态播报并提供可直接复制的 HTML、React、Next.js 与 CSS 实现。读完本文后你将能够识别并修复分页组件中的无障碍缺陷用navaria-currentpage构建符合规范的分页标记实现带实时区域live region播报的 React 分页组件并完成一套覆盖键盘与屏幕阅读器的验证清单。快速参考TL;DRpagination-accessibility规则的核心要求可以浓缩为四条见 SKILL.md使用nav元素并设置aria-labelPagination用aria-currentpage标记当前页为上一页/下一页按钮提供清晰的aria-label页面切换时向屏幕阅读器播报变化。该技能在仓库中的元信息为类别html、优先级medium、难度beginner、预估耗时 20 分钟其规则正文与实现细节维护在 references/rule.md而面向站点的正式规则版本位于 packages/content/rules/en/html/pagination-accessibility.mdx。为什么分页可访问性重要没有正确的标记屏幕阅读器用户无法理解自己正处于哪一页也无法在分页内容中高效导航。这是该规则whyItMatters字段的原文。分页控件对视觉用户来说看起来很清楚但对辅助技术用户而言一组没有语义的数字链接只是一堆无差别的文本。具体而言位置感知aria-currentpage让屏幕阅读器播报第 2 页当前页用户才能知道自己在哪导航效率nav地标landmark允许屏幕阅读器用户通过地标快速跳转而不是逐个 Tab 遍历每个分页链接状态可感知当分页在无整页刷新的情况下替换内容时如果不通过实时区域播报屏幕阅读器用户甚至不知道页面内容已经更新。该规则在仓库中还与 navigation-landmark.mdx导航地标区域、breadcrumb-navigation面包屑导航等规则被标记为相关联它们常常在同一实现中同时被评审。Check如何检查分页是否无障碍根据规则中的prompts.check检查步骤如下分页是否使用nav元素并带有aria-label当前页是否通过aria-current指示所有控件是否可键盘导航focusable。规则同时强调aiContext字段审查时应以最终浏览器可见的标记rendered HTML为准而非仅看源码框架层的抽象。也就是说React/Vue 组件里写得再规范也要确认最终渲染出的 DOM 确实包含这些属性。Fix无障碍分页的标准标记规则给出的修复要点是使用nav rolenavigation、aria-label、对当前页使用aria-currentpage并确保所有控件可聚焦。以下是最小可用的无障碍分页 HTML 示例来自 references/rule.mdnav aria-labelPagination classpagination ul li a href?page1 aria-labelGo to previous page Previous /a /li li a href?page1 aria-labelPage 11/a /li li a href?page2 aria-currentpage aria-labelPage 2, current page2/a /li li a href?page3 aria-labelPage 33/a /li li span aria-hiddentrue.../span /li li a href?page10 aria-labelPage 1010/a /li li a href?page3 aria-labelGo to next page Next /a /li /ul /nav注意几个细节省略号...只是视觉占位必须用aria-hiddentrue隐藏避免屏幕阅读器播报无意义的省略号上一页/下一页链接的可见文本是 Previous/Next但通过aria-label提供了更完整的描述当前页链接的aria-label是 Page 2, current page与aria-currentpage互补给出明确的位置信息。无障碍需求对照表references/rule.md 将需求与实现方案整理成表需求实现方式容器Containernav带aria-labelPagination当前页Current pagearia-currentpage页面标签Page labels为屏幕阅读器提供描述性文本键盘访问Keyboard access所有控件可聚焦状态变化State changes通过实时区域live regions播报无障碍分页的 React 实现当分页完全由前端状态驱动无整页刷新时需要用 React 实现。仓库的 references/rule.md 给出了完整组件核心逻辑包括页码生成算法始终显示第 1 页与最后一页中间用siblingCount默认 1控制当前页两侧的页码数量超出范围用ellipsis占位边界处理首页时上一页按钮disabled末页时下一页按钮disabled当前页标记aria-current{page currentPage ? page : undefined}动态标签当前页播报Page ${page}, current page其他页播报Go to page ${page}状态播报切换页面时通过useState记录Page ${page} of ${totalPages}并渲染到一个aria-livepolite aria-atomictrue的视觉隐藏区域。完整组件如下references/rule.mdinterface PaginationProps { currentPage: number totalPages: number onPageChange: (page: number) void siblingCount?: number } export function Pagination({ currentPage, totalPages, onPageChange, siblingCount 1 }: PaginationProps) { const [announcement, setAnnouncement] useState() const getPageNumbers () { const pages: (number | ellipsis)[] [] const leftSibling Math.max(currentPage - siblingCount, 1) const rightSibling Math.min(currentPage siblingCount, totalPages) // Always show first page if (leftSibling 1) { pages.push(1) if (leftSibling 2) pages.push(ellipsis) } // Show sibling pages for (let i leftSibling; i rightSibling; i) { pages.push(i) } // Always show last page if (rightSibling totalPages) { if (rightSibling totalPages - 1) pages.push(ellipsis) pages.push(totalPages) } return pages } const handlePageChange (page: number) { onPageChange(page) setAnnouncement(Page ${page} of ${totalPages}) } const pageNumbers getPageNumbers() return ( nav aria-labelPagination classNamepagination ul classNamepagination__list {/* Previous button */} li button typebutton onClick{() handlePageChange(currentPage - 1)} disabled{currentPage 1} aria-labelGo to previous page classNamepagination__button ← Previous /button /li {/* Page numbers */} {pageNumbers.map((page, index) page ellipsis ? ( li key{ellipsis-${index}} aria-hiddentrue span classNamepagination__ellipsis.../span /li ) : ( li key{page} button typebutton onClick{() handlePageChange(page)} aria-current{page currentPage ? page : undefined} aria-label{ page currentPage ? Page ${page}, current page : Go to page ${page} } className{pagination__button ${ page currentPage ? pagination__button--current : }} {page} /button /li ) )} {/* Next button */} li button typebutton onClick{() handlePageChange(currentPage 1)} disabled{currentPage totalPages} aria-labelGo to next page classNamepagination__button Next → /button /li /ul /nav {/* Live region for announcements */} div aria-livepolite aria-atomictrue classNamesr-only {announcement} /div / ) }这里的关键机制是live region实时区域aria-livepolite让屏幕阅读器在不打断当前朗读的情况下播报更新aria-atomictrue表示整个区域内容变化时整体播报sr-only类确保它在视觉上隐藏但仍在辅助技术树中。带每页条数选择器的变体真实产品中通常还需要每页显示条数选择器与结果计数信息。仓库提供了PaginationWithSize组件references/rule.md核心点包括用aria-livepolite的p播报Showing X to Y of Z results让屏幕阅读器用户感知数据范围变化每页条数选择器使用原生label htmlForpage-sizeselect idpage-size关联支持 10/25/50/100 四档见 references/rule.md组合方式为startItem (currentPage - 1) * pageSize 1、endItem Math.min(currentPage * pageSize, totalItems)。interface PaginationWithSizeProps extends PaginationProps { pageSize: number totalItems: number onPageSizeChange: (size: number) void } export function PaginationWithSize({ currentPage, totalPages, pageSize, totalItems, onPageChange, onPageSizeChange }: PaginationWithSizeProps) { const startItem (currentPage - 1) * pageSize 1 const endItem Math.min(currentPage * pageSize, totalItems) return ( div classNamepagination-container {/* Page info */} p classNamepagination__info aria-livepolite Showing {startItem} to {endItem} of {totalItems} results /p {/* Page size selector */} div classNamepagination__size label htmlForpage-sizeItems per page:/label select idpage-size value{pageSize} onChange{(e) onPageSizeChange(Number(e.target.value))} option value{10}10/option option value{25}25/option option value{50}50/option option value{100}100/option /select /div {/* Pagination controls */} Pagination currentPage{currentPage} totalPages{totalPages} onPageChange{onPageChange} / /div ) }URL 驱动的分页Next.js当分页状态需要反映在 URL 查询参数中便于分享、收藏和 SEO时可以在 Next.js App Router 下用useRouter与useSearchParams实现references/rule.mduse client import { useRouter, useSearchParams } from next/navigation interface URLPaginationProps { totalPages: number } export function URLPagination({ totalPages }: URLPaginationProps) { const router useRouter() const searchParams useSearchParams() const currentPage Number(searchParams.get(page)) || 1 const handlePageChange (page: number) { const params new URLSearchParams(searchParams) params.set(page, String(page)) router.push(?${params.toString()}) } return ( Pagination currentPage{currentPage} totalPages{totalPages} onPageChange{handlePageChange} / ) }要点Number(searchParams.get(page)) || 1缺失或非法的page参数回退到第 1 页通过URLSearchParams保留其他查询参数只更新page由于 URL 会变化浏览器前进/后退可以正常工作这是无障碍之外额外的可用性收益。样式实现与响应式降级仓库为上述组件配套了完整 CSSreferences/rule.md值得注意的几点按钮最小尺寸min-width: 2.5rem、height: 2.5rem满足触控目标与可点击区域要求焦点样式用:focus-visible { outline: 2px solid #0066cc; outline-offset: 2px; }只有键盘导航时才显示焦点环不干扰鼠标操作:disabled状态降低透明度并禁用指针事件移动端降级media (max-width: 640px)下隐藏中间页码只保留上一页/下一页references/rule.md但按钮仍是原生可聚焦控件因此键盘/屏幕阅读器可用性不受影响.sr-only是标准的视觉隐藏类用于承载 live region 的播报文本。验证清单如何确认分页真正无障碍references/rule.md 给出 7 步验证流程用键盘导航Tab 遍历所有控件确认每个链接/按钮都可聚焦验证屏幕阅读器能播报当前页检查aria-label是否描述清晰测试第一页/最后一页时按钮的禁用状态验证页面切换的播报live region 是否生效检查页面切换后焦点是否正确返回用屏幕阅读器完整走一遍分页流程。其中第 6 点值得展开当分页切换内容而不发生整页跳转时焦点不应丢失。如果焦点留在分页控件上用户会立即感知到状态变化如果内容被替换后焦点被重置到页面顶部用户会迷失方向。规则同时给出了一条明确的补充警告当分页在没有整页刷新的情况下改变内容时请使用aria-live区域播报这一变化。用户应该知道内容已更新。这也解释了为什么 React 组件中 live region 与setAnnouncement(Page X of Y)是必须存在的部分而非锦上添花。关联规则与进一步阅读分页可访问性不是孤立的规则。在仓库的规则体系中它与以下规则关联最紧密见 pagination-accessibility.mdx 的relatedRules字段breadcrumb-navigation.mdx同属html/navigation区域两者常一起被评审navigation-landmark.mdx分页nav本质上是导航地标与用 nav 元素 aria-label 区分多个导航区域的规则互相印证同级技能文档还包含 skills/carousel-accessibility/SKILL.md轮播可访问性与accessible-notifications可访问通知等规则它们关注动态内容变化如何对辅助技术可见这一共同主题。如果需要进一步探索可以阅读正式规则与元数据packages/content/rules/en/html/pagination-accessibility.mdx技能定义含 check/fix/explain/code review 提示词skills/pagination-accessibility/SKILL.md完整实现细节skills/pagination-accessibility/references/rule.md。小结无障碍分页的实质是三件事语义化容器navaria-label、当前位置指示aria-currentpage、状态变化播报aria-live。在此基础上配合描述性的aria-label、可聚焦的原生控件、边界禁用状态和移动端降级就能同时满足键盘用户、屏幕阅读器用户和触屏用户的需求。无论你是从零实现还是在代码评审中对照 references/rule.md 检查模板与服务端渲染的 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创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考