必须使用原生实现滑块,因其自带完整aria语义、键盘交互(←→↑↓/page up/down)和无障碍支持;禁用自定义div+js方案,避免焦点、朗读、范围值同步等无障碍失效问题。

滑块元素必须用 <input type="range">,别手写 div 模拟
手动用 <div> + JS 实现的“滑块”几乎必然失败:键盘无法聚焦、方向键无效、屏幕阅读器读不出当前值和范围。原生 <code><input type="range"> 自带完整的 ARIA 语义和键盘交互(←/→ 调整 1 步,↑/↓ 同样生效,Page Up/Page Down 调整 10 倍 step),这是无障碍底线。
常见错误现象:role="slider" 加在非原生控件上,但没实现 aria-valuenow 动态同步、没处理 keydown 事件、没设 aria-valuemin/aria-valuemax —— 屏幕阅读器会直接跳过或报“未知控件”。
- 必须设置
min、max、step和value属性(哪怕初始值是 0) - 禁用
tabindex:原生input默认可聚焦,加tabindex="0"可能导致重复焦点 - 不要包裹在
<label></label>里再用for关联 —— 直接用<label for="id"></label>或把input放进<label></label>内部更可靠
aria-label 或 <label></label> 二选一,不能都省
没有可见文本标签的滑块,屏幕阅读器无法告知用户“这是调节什么的”。只靠 placeholder 或旁边文字说明(非 <label></label> 关联)是无效的。
使用场景:音量控制、字体大小调节、时间轴拖动等隐式语义强的控件,必须明确传达目的。
- 优先用
<label></label>包裹:<label>字体大小<input type="range" id="fs" min="12" max="24" step="2" value="16"></label>
- 若视觉上不能显示标签(如工具栏图标旁小滑块),用
aria-label="调节对比度",但需确保该描述足够具体(“调节滑块”这种无效) - 避免同时写
<label></label>和aria-label:会导致重复朗读
动态更新 aria-valuetext 要谨慎,多数情况不需要
aria-valuetext 用于提供比数值更自然的描述(例如 “中等亮度” 而非 “50”),但它会覆盖屏幕阅读器对 aria-valuenow 的默认朗读。滥用反而降低可理解性。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
性能影响:每次拖动都触发 DOM 更新 + 屏幕阅读器重读,可能卡顿;兼容性风险:旧版 NVDA 对频繁变更的 aria-valuetext 支持不稳定。
- 仅当数值本身无意义时才用:比如色温滑块 2000K–6500K,可设
aria-valuetext="暖光"/"冷光" - 必须配合
aria-valuenow使用,不能单独存在 - 更新时用
element.setAttribute('aria-valuetext', text),别用innerHTML或其他间接方式
移动端 Safari 和旧版 Android WebView 有 focus 焦点穿透问题
部分 iOS 版本下,<input type="range"> 在触摸后不触发 focus 事件,导致依赖 :focus 的样式(如外框高亮)失效,也影响某些 JS 逻辑(如自动朗读当前值)。
根本原因:WebKit 将触摸视为“指针操作”,不模拟键盘焦点流。这不是 bug,是平台行为差异。
- 用
ontouchstart+element.focus()强制补焦(注意防重复) - 视觉反馈别只靠
:focus:叠加:active或 JS 添加临时 class - 测试真机:Chrome DevTools 的设备模拟器无法复现此问题










