轮播组件无障碍优化:屏蔽屏幕阅读器读隐藏内容且保留总项数提示
轮播组件无障碍优化:屏蔽隐藏内容同时保留总项数提示
核心问题拆解
你遇到的矛盾点在于:直接给隐藏项加aria-hidden="true"会让屏幕阅读器把列表计数从总项数改成当前可见项数,而不加的话又会读取隐藏内容。解决方案的关键是用ARIA属性明确声明列表的总项数,同时单独控制隐藏项的可读性。
具体实现方案
- 给列表容器声明总项数:通过
aria-setsize属性告诉屏幕阅读器整个轮播的总项目数量,不管当前显示多少项,这个值始终是总条数。 - 给可见项标记位置:用
aria-posinset给每个可见项标注它在总列表中的序号,帮助用户理解当前看到的是哪一部分。 - 单独隐藏不可见项:仅对当前不在可视区域的项设置
aria-hidden="true",阻止屏幕阅读器读取,但不影响列表的总计数。
React代码示例
import { useState } from 'react'; const Carousel = ({ items }) => { const [currentPos, setCurrentPos] = useState(0); const totalItems = items.length; const visibleCount = 3; const handleNext = () => { if (currentPos + visibleCount < totalItems) { setCurrentPos(prev => prev + 1); } }; const handlePrev = () => { if (currentPos > 0) { setCurrentPos(prev => prev - 1); } }; return ( <div className="carousel-wrapper"> {/* 上一页按钮:添加明确的ARIA标签 */} <button onClick={handlePrev} disabled={currentPos === 0} aria-label="查看上一组项目" > ← </button> {/* 列表容器:用aria-setsize声明总项数 */} <ul className="carousel-list" aria-setsize={totalItems} style={{ display: 'flex', overflow: 'hidden', width: `${3 * 220}px`, // 按实际项宽调整 listStyle: 'none', padding: 0, margin: 0 }} > {items.map((item, idx) => { const isVisible = idx >= currentPos && idx < currentPos + visibleCount; return ( <li key={idx} style={{ width: '220px', flexShrink: 0, transform: isVisible ? 'none' : 'translateX(-100%)', transition: 'transform 0.3s' }} aria-hidden={!isVisible} {/* 仅可见项设置位置序号 */} {...isVisible && { 'aria-posinset': idx + 1 }} > {item.title} </li> ); })} </ul> {/* 下一页按钮:添加明确的ARIA标签 */} <button onClick={handleNext} disabled={currentPos + visibleCount >= totalItems} aria-label="查看下一组项目" > → </button> </div> ); }; export default Carousel;
关键属性说明
aria-setsize={totalItems}:强制屏幕阅读器识别列表的总项数,比如总共有6项,即使只显示3个,也会提示“列表,6项”。aria-posinset:给可见项标记它在总列表中的位置,比如当前显示第1-3项,屏幕阅读器会分别提示“第1项,共6项”“第2项,共6项”等。aria-hidden={!isVisible}:仅对隐藏项设置,阻止屏幕阅读器读取这些内容,但不会影响列表的整体计数。
测试验证(Mac VoiceOver)
- 打开VoiceOver(快捷键
Cmd + F5)。 - 聚焦到轮播列表时,VoiceOver会提示“列表,6项”。
- 聚焦到单个可见项时,会提示“第X项,共6项”。
- 隐藏项不会被VoiceOver读取,切换页码时也只会读取当前可见的项。
额外注意点
- 不要用
display: none隐藏项:这种方式会让屏幕阅读器完全忽略该元素,反而可能影响计数,用transform或position做视觉隐藏配合aria-hidden更合适。 - 控制按钮要加语义化标签:确保屏幕阅读器用户知道按钮的作用,禁用状态也要保留
disabled属性,VoiceOver会提示“禁用的按钮”。
内容的提问来源于stack exchange,提问作者kar
相关产品推荐
相关产品推荐

