概述语义化结构与ARIA属性使组件对读屏与键盘用户友好。焦点管理与键盘导航确保在对话框与菜单等复杂组件中交互可达与一致。关键实践与参数语义结构: 使用原生元素与role属性传达语义对话框: role=dialog, aria-modal, aria-labelledby菜单导航: role=menu与方向键导航焦点陷阱: 打开对话框时限制焦点在内部评估工具: Lighthouse与axe对可访问性评分示例/配置/实现<button id="open">打开</button>
<div id="dialog" role="dialog" aria-modal="true" aria-labelledby="title" hidden>
<h2 id="title">标题</h2>
<button id="close">关闭</button>
<nav role="menu">
<button role="menuitem">项1</button>
<button role="menuitem">项2</button>
</nav>
</div>
const open = document.getElementById('open')
const close = document.getElementById('close')
const dialog = document.getElementById('dialog')
let lastFocus
function trapFocus(e) {
const focusables = dialog.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')
if (!focusables.length) return
const first = focusables[0]
const last = focusables[focusables.length - 1]
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === first) { last.focus(); e.preventDefault() }
else if (!e.shiftKey && document.activeElement === last) { first.focus(); e.preventDefault() }
}
}
open.addEventListener('click', () => { lastFocus = document.activeElement; dialog.hidden = false; dialog.focus(); document.addEventListener('keydown', trapFocus) })
close.addEventListener('click', () => { dialog.hidden = true; document.removeEventListener('keydown', trapFocus); if (lastFocus) lastFocus.focus() })
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
const items = Array.from(dialog.querySelectorAll('[role="menuitem"]'))
const i = items.indexOf(document.activeElement)
const n = e.key === 'ArrowDown' ? Math.min(i + 1, items.length - 1) : Math.max(i - 1, 0)
items[n].focus()
}
})
验证键盘可达性: 仅用键盘完成对话框打开与菜单导航焦点一致性: 打开时焦点进入组件内部, 关闭后回到触发按钮读屏语义: 读屏报读标题与对话框语义正确评分改进: Lighthouse与axe评分提升并无严重问题注意事项避免滥用ARIA, 优先使用原生语义元素样式与焦点状态需清晰可见国际化文本需为读屏友好在复杂组件中保持焦点顺序与逻辑一致

发表评论 取消回复