无障碍✅
页面语义化与地标如何设计?
答案
核心要点
- 语义元素:
header/nav/main/aside/footer
让辅助技术快速定位结构 - 跳转链接:提供“跳到主要内容”的 skip-link
- landmark 命名:为导航/页脚等添加
aria-label
提升可辨识度
<!doctype html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>语义化结构与地标</title> <style> body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial; line-height: 1.6; } .skip-link { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; } .skip-link:focus { position: static; width: auto; height: auto; } header, nav, main, aside, footer { padding: 8px 12px; margin: 8px 0; border: 1px dashed #bbb; } nav a { margin-right: 8px; } </style> <link rel="stylesheet" href="https://unpkg.com/mvp.css" /> </head> <body> <a href="#main" class="skip-link">跳到主要内容</a> <header aria-label="站点头部"> <h1>示例站点</h1> </header> <nav aria-label="主导航"> <a href="#">首页</a> <a href="#">产品</a> <a href="#">关于</a> </nav> <main id="main"> <article> <h2>文章标题</h2> <p>使用 header/nav/main/footer 等语义元素有助于辅助技术快速定位页面结构。</p> </article> </main> <aside aria-label="侧边栏"> <p>侧栏信息</p> </aside> <footer aria-label="页脚"> <p>© 2025 示例</p> </footer> </body> </html>
面试官视角
- 关注能否正确使用语义元素、跳转链接与地标命名
延伸阅读
按钮组件的可访问性该如何实现?
答案
核心要点
- 使用
button
而非div
,天然可聚焦与键盘可触达 - 状态宣告:结合
role="status"
或aria-live
提示结果
<!doctype html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>可访问按钮</title> <link rel="stylesheet" href="https://unpkg.com/mvp.css" /> </head> <body> <h1>按钮可访问性</h1> <p>使用 button 元素而不是 div+click;确保可聚焦、键盘可触达、状态可感知。</p> <button type="button" id="btn">提交</button> <p id="status" role="status" aria-live="polite"></p> <script> const btn = document.getElementById('btn') const status = document.getElementById('status') btn.addEventListener('click', () => { status.textContent = '已提交' console.log('按钮被点击,并通过 role="status" 宣告') }) </script> </body> </html>
面试官视角
- 关注是否避免
div+click
且支持键盘和读屏状态宣告
延伸阅读
表单如何实现标签关联与错误宣告?
答案
核心要点
label for
绑定输入,aria-describedby
绑定错误提示- 错误消息使用
role="alert"
或 live region 动态宣告
<!doctype html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>可访问表单</title> <link rel="stylesheet" href="https://unpkg.com/mvp.css" /> </head> <body> <h1>表单可访问性</h1> <form aria-describedby="form-desc"> <p id="form-desc">所有输入都有 <code>label</code> 关联,错误通过 <code>aria-describedby</code> 宣告。</p> <label for="email">邮箱</label> <input id="email" name="email" type="email" required aria-describedby="email-err" /> <small id="email-err" role="alert" aria-live="polite"></small> <label for="pwd">密码</label> <input id="pwd" name="pwd" type="password" required /> <button>提交</button> </form> <script> const form = document.querySelector('form') const email = document.getElementById('email') const emailErr = document.getElementById('email-err') form.addEventListener('submit', (e) => { e.preventDefault() if (!email.value.includes('@')) { emailErr.textContent = '请输入有效邮箱地址' email.focus() return } emailErr.textContent = '' console.log('表单通过基础校验') }) </script> </body> </html>
面试官视角
- 关注“标签-输入”可达性、错误宣告及时与聚焦管理
延伸阅读
模态对话框如何保证键盘可达和焦点管理?
答案
核心要点
- 语义:
role="dialog"
+aria-modal="true"
+aria-labelledby/aria-describedby
- 焦点:开启时将焦点移入,关闭时还原;Esc 关闭
<!doctype html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>可访问对话框</title> <link rel="stylesheet" href="https://unpkg.com/mvp.css" /> <style> .backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); display: none; } .dialog { background: #fff; margin: 10% auto; max-width: 480px; padding: 16px; outline: none; } .backdrop[aria-hidden="false"] { display: block; } </style> </head> <body> <h1>模态对话框可访问性</h1> <button id="open">打开对话框</button> <div class="backdrop" id="backdrop" aria-hidden="true"> <div class="dialog" role="dialog" aria-modal="true" aria-labelledby="title" aria-describedby="desc" tabindex="-1"> <h2 id="title">删除确认</h2> <p id="desc">此操作不可撤销,确认继续吗?</p> <button id="confirm">确认</button> <button id="close">取消</button> </div> </div> <script> const openBtn = document.getElementById('open') const backdrop = document.getElementById('backdrop') const dialog = backdrop.querySelector('.dialog') const closeBtn = document.getElementById('close') const confirmBtn = document.getElementById('confirm') function open () { backdrop.setAttribute('aria-hidden', 'false') dialog.focus() document.addEventListener('keydown', onKeydown) console.log('Dialog opened') } function close () { backdrop.setAttribute('aria-hidden', 'true') openBtn.focus() document.removeEventListener('keydown', onKeydown) console.log('Dialog closed') } function onKeydown (e) { if (e.key === 'Escape') close() } openBtn.addEventListener('click', open) closeBtn.addEventListener('click', close) confirmBtn.addEventListener('click', close) </script> </body> </html>
面试官视角
- 关注焦点圈定、关闭快捷键、可返回原触发点
延伸阅读
动态内容如何被读屏及时宣告?
答案
核心要点
- 使用
aria-live
区域(polite
/assertive
)宣告异步状态 - 适用于通知、加载、完成等动态反馈
<!doctype html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Live Region</title> <link rel="stylesheet" href="https://unpkg.com/mvp.css" /> </head> <body> <h1>动态内容宣告(ARIA Live)</h1> <button id="add">开始任务</button> <div role="status" aria-live="polite" id="status"></div> <script> const status = document.getElementById('status') document.getElementById('add').addEventListener('click', () => { status.textContent = '任务已开始…' setTimeout(() => { status.textContent = '任务完成' console.log('通过 role="status" 宣告任务完成') }, 1200) }) </script> </body> </html>
面试官视角
- 关注宣告时机与语气等级选择是否得当
延伸阅读
图像的替代文本应如何编写?
答案
核心要点
- 装饰性图片使用空
alt
;信息性图片使用简洁的描述 - 图表可结合
figure/figcaption
补充上下文
<!doctype html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>图像可访问性</title> <link rel="stylesheet" href="https://unpkg.com/mvp.css" /> </head> <body> <h1>图像文本替代</h1> <p>装饰性图片用空 <code>alt</code>;信息性图片用简洁 <code>alt</code> 描述。</p> <img src="https://dummyimage.com/120x60/ddd/000&text=Logo" alt="示例站点 LOGO" /> <img src="https://dummyimage.com/80x80/eee/aaa" alt="" /> <figure> <img src="https://dummyimage.com/320x180/ccc/000&text=Sales+2025" alt="2025 年销售趋势折线图" /> <figcaption>图 1:销售趋势</figcaption> </figure> </body> </html>
面试官视角
- 关注是否能区分装饰性与信息性图片,并给出合适 alt 描述
延伸阅读