html语义化本身不破坏可访问性,但忽略doctype首行空格、aria同步及旧浏览器解析边界会导致语义标签退化为div、aria属性被忽略、屏幕阅读器无法识别结构。

HTML语义化演进本身不会破坏可访问性,但开发者若忽略渲染模式、ARIA同步和旧浏览器的解析边界,就会让新标签在关键场景下“失效”。
DOCTYPE 必须首行无空格,否则 IE/Edge 进入 Quirks Mode
哪怕只多一个 BOM 或换行前空格, 就会失效。后果不是样式错乱那么简单——<code>role、aria- 属性被完全忽略,<nav></nav>、<main></main> 等语义标签退化为普通 <div>,屏幕阅读器读不出结构。
<ul>
<li>验证方式:Chrome DevTools → Elements 面板顶部看渲染模式,必须显示 <code>Standards;若为 Quirks,立刻检查源码开头
head -c 10 file.html | grep -q "^ 确保 DOCTYPE 紧贴首行
"files.encoding": "utf8",禁用 "files.autoGuessEncoding")HTML5 标签在 IE8 及以下需 html5shiv + display:block 手动补全
html5shiv 仅解决 DOM 创建问题,不自动设置样式。IE8 默认把 <section></section> 当作未知内联元素,导致子元素塌陷、浮动失效、无障碍 API 不识别。
- 必须在
中引入后,显式重置显示行为:header, nav, main, section, article, aside, footer { display: block; } - 不要依赖 CSS Reset 或 Normalize.css 的兜底——它们对 HTML5 新标签的
display声明在 IE8 下无效 - 若项目仍需支持 IE8,
<main></main>标签建议暂不使用(IE 全系原生不支持),改用<div role="main"> 并确保 JS 动态更新时同步操作 <code>aria-hiddenARIA 属性必须与 DOM 状态实时同步,不能只靠 class 切换
仅用
class="active"标记当前导航项,对屏幕阅读器毫无意义。用户无法感知“我在哪”,尤其当多个链接文字相同时(如多个“详情”)。- 正确写法:
@#@#@#@#@#@#@#@#@#@0——aria-current="page"是唯一被主流读屏广泛支持的合法值 - JS 更新导航状态时,必须同时操作:
el.setAttribute('aria-current', 'page')和el.removeAttribute('aria-current'),不能只改 class - 避免
aria-current="true":WAI-ARIA 规范未定义该值,NVDA 2025.2+ 会静默忽略,VoiceOver 在 macOS 14+ 报 warning
多
<nav></nav>共存时必须用aria-label或aria-labelledby区分用途两个
<nav></nav>不加区分,屏幕阅读器会把它们合并识别为“一个导航区域”,用户无法跳转到“页脚快速链接”这类次要导航。- 主导航:
<nav aria-label="主导航"><ul>...</ul></nav> - 页脚导航:
<nav aria-label="页脚站点地图"><ul>...</ul></nav> - 绝对不要用
aria-label="navigation"这类泛化描述——它等于没标;也别用id+aria-labelledby指向不可见文本,部分读屏对隐藏文本支持不稳定
真正难的不是写对新标签,而是每次新增语义结构时,都得反问一句:这个标签在 IE11 的标准模式下是否被识别?在 NVDA 的“结构视图”里能否被单独列出?在键盘 Tab 流中是否自然进入又退出?这些边界条件,比语法本身更消耗判断力。
- 正确写法:











