修复穿梭框无障碍问题需三步:一是将模拟按钮改为语义化并添加aria-label和disabled属性;二是用aria-live="polite"动态播报操作结果;三是为多选框添加aria-label和aria-describedby关联实时计数,同时保留按钮操作路径而非仅依赖拖拽。

左右移动按钮没键盘焦点,怎么修复?
原生 <button></button> 默认可聚焦、可回车触发,但很多穿梭框用 <div> 或 <code><span></span> 模拟按钮,导致键盘用户完全无法操作。必须确保移动按钮是语义化、可聚焦的元素。
实操建议:
- 把
<div class="btn-right">→</div>改成<button type="button" aria-label="将选中项移至右侧">→</button> - 禁用状态不要只靠
opacity: 0.5或pointer-events: none,要加disabled属性(<button disabled></button>)并配合aria-disabled="true"兼容旧读屏器 - 如果用自定义标签(如
<span role="button"></span>),必须手动加tabindex="0"、监听Enter和Space键,且视觉上要体现焦点环(别用outline: none且不替换)
穿梭后屏幕阅读器不播报变化,怎么通知?
用户点击“→”把 3 个选项移到右侧,读屏器默认不会说“已添加:苹果、香蕉、橙子”,因为 DOM 变更未附带语义提示。
实操建议:
- 在移动操作完成后的 JS 中,动态创建一个
<div aria-live="polite"></div>(推荐挂载在底部),然后插入文本:div.textContent = `已移入 ${selected.length} 项` - 避免用
aria-live="assertive",它会中断当前播报;polite更稳妥 - 不要依赖
alert()或console.log()——前者打断操作流,后者对读屏器无效
左右 select 多选框被读作“下拉列表”,怎么改?
原生 <select multiple></select> 在多数读屏器里被识别为“combobox”或“listbox”,但缺乏上下文。用户不知道左边是“待选”,右边是“已选”,也不知道当前有多少项被选中。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
实操建议:
- 给每个
<select></select>加aria-label,例如:<select id="left" aria-label="待选项目列表,可多选"></select> - 用
aria-describedby关联实时计数:<select aria-describedby="left-count">...</select><div id="left-count">共 12 项,当前选中 2 项</div>,并在 JS 中同步更新该<div> 的文本 <li>避免仅靠视觉样式(如“左侧栏”文字)传达结构——读屏器不会自动读出相邻普通文本</li> <h3>拖拽穿梭时键盘用户完全被绕过,怎么办?</h3> <p>拖拽(<code>dragstart/drop)天生不可键盘操作,且多数读屏器不监听 drag 事件。一旦你把“拖到右边”设为主要交互方式,等于主动放弃键盘和读屏用户。实操建议:
- 拖拽只能作为增强手段,**必须保留按钮触发路径**(如“→”“←”“全部→”)并保证其功能完整、逻辑一致
- 不要隐藏按钮或设为
display: none;可用clip-path+position: absolute实现视觉隐藏但保留可访问性(即“screen reader only”) - 若坚持用拖拽,至少在
dragenter时通过aria-live提示“松开鼠标可放入右侧”,但别指望它能替代按钮
aria-describedby和aria-live的更新时机稍有延迟,就会让用户迷失在无声的变更里。










