html语义化标签是无障碍访问的底层路基,而非附加功能;等原生标签自带role并支持快捷键跳转,而无语义,屏幕阅读器仅逐字朗读,导致用户操作延迟超8秒。

HTML语义化标签不是无障碍的“附加功能”,而是无障碍通道的底层路基——没有它,ARIA、键盘导航、屏幕阅读器都得在沙地上修桥。
为什么 screen reader 一进页面就“懵”?
屏幕阅读器(如 VoiceOver、TalkBack)不靠视觉识别结构,而是解析 DOM 中的语义角色(role)、状态(state)和名称(name)。当全用 <div class="nav"> 时,它读不出“这是导航”,只能逐字念“div、div、a、div……”,用户得手动滑动 10+ 次才能找到登录入口。
<p>而换成 <code><nav aria-label="主导航"></nav>,VoiceOver 会直接播报“主导航,包含 5 个链接”,按 H 键跳标题、按 N 键跳导航——这一步省掉的不是代码,是用户 8 秒以上的操作等待。
-
<header></header>、<main></main>、<footer></footer>提供全局区域跳转锚点;旧版 Safari ≤13.1 需显式加role="main"才触发正确 API 调用 -
<section></section>必须以<h2></h2>–<h6></h6>开头,否则退化为普通<div>,读屏无法建立内容层级 <li> <code><figure><figcaption></figcaption></figure>让图像与说明形成明确归属关系,TalkBack 不会把图注当成独立段落乱读 - 自定义下拉组件没用
<select></select>,就得用role="combobox"+aria-expanded+aria-controls - 密码强度提示放在输入框下方,用
aria-describedby="pwd-hint"关联,读屏才会连起来读 - 错误消息弹出后,用
role="alert"或aria-live="assertive"确保即时播报,而不是等用户滚动到才读 -
<header></header>塞进 logo + 导航 + 搜索框 → VoiceOver 统一读作“banner”,失去内部结构,用户无法单独跳导航 -
<footer></footer>直接丢在底部,没包裹任何内容 → 多数安卓 WebView 忽略其语义,不提供“跳页脚”快捷键 - 用
<div role="button"> 替代 <code><button></button>→ 键盘 Tab 可聚焦,但回车/空格不触发,还得手写keydown监听,且不支持:focus-visible样式语义标签本身不加速渲染,但错用会拖慢 JS 查询(比如 6 层
<section></section>嵌套让document.querySelector多遍历 300+ 节点),更关键的是:它决定了无障碍通道是“高速公路”还是“泥泞小道”——后者修得再漂亮,轮椅也推不进去。
表单里写 aria-required="true" 还是用原生 required?
优先用原生 required 属性。它自带语义 + 浏览器默认校验逻辑 + 键盘焦点自动回退,而 aria-required="true" 只告诉读屏“这个要填”,不触发任何行为。混合使用反而可能造成状态不一致:比如 JS 清空了值但没同步更新 aria-invalid,读屏说“已填写”,实际提交失败。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
真正需要 ARIA 的场景是原生能力覆盖不到的地方:
移动端特别容易翻车的三个语义陷阱
在 iOS 和安卓 WebView 中,语义失效往往不是“没效果”,而是“效果反向”:










