lang属性必须写在<html>标签上,否则屏幕阅读器直接fallback英文引擎,将“北京”读作“B-e-i-j-i-n-g”;值须严格符合BCP 47标准(如zh-CN),错误则静默忽略。

lang 属性必须写在 <html> 标签上,否则屏幕阅读器根本不会按你写的语言读——它不是“读得不准”,而是直接 fallback 到英文引擎,把“北京”念成 “B-e-i-j-i-n-g”。
为什么只认 <html lang="xx-XX">?
NVDA、VoiceOver、JAWS 这些主流屏幕阅读器,只在初始解析 HTML 时读取 <html> 的 lang 值,用它初始化整页语音引擎。其他位置全无效:
-
<body lang="zh-CN">:被当作局部覆盖,不影响全局发音基础 -
<meta http-equiv="Content-Language">:HTML5 已废弃,现代 AT 完全忽略 -
<div lang="en">:只对内部文本生效,且前提是根lang已正确设置
lang 值写错等于没写
浏览器静默忽略非法值,等效于页面无语言声明。常见错误包括:
-
lang="zh":太宽泛,旧版 JAWS 和 iOS VoiceOver fallback 英文 -
lang="zh_CN":下划线非法,必须用短横线zh-CN -
lang="Chinese":非标准标签,完全不识别 -
lang="zh-CN ":末尾空格导致解析失败,Lighthouse报invalid language subtag
推荐值:zh-CN(大陆简体)、zh-TW(台湾繁体)、zh-HK(香港繁体)。zh-Hans 可用但兼容性略窄,zh-Hans-CN 是非法组合。
立即学习“前端免费学习笔记(深入)”;
中英文混排时,根 lang 不够用
根 lang="zh-CN" 只设默认行为;遇到英文术语、代码、引文,屏幕阅读器仍会用中文规则硬读,比如 “API” 变 “阿皮”,“React” 变 “瑞克特”。必须显式标注:
- 单个外文词或代码标识符:
<code lang="en">fetch()</code>(比<span>更语义准确,部分读屏对<code>有特殊停顿) - 整段英文说明:
<p lang="en">The response is a JSON object.</p> - 避免滥用:
<div lang="en">包裹多段落——语义不清,还可能干扰:lang(en)CSS 选择器匹配
JS 动态改 lang 对已渲染内容无效
执行 document.documentElement.lang = "en-US" 后:
- 只影响后续插入的 DOM 节点
- 页面已存在的文本、已挂载组件、已绑定的
:lang(zh)CSS 伪类,全部不会重计算 - SSR 场景下,若首屏 HTML 没带
lang,爬虫和 AT 拿到的就是空值,JS 补救为时已晚
最麻烦的不是写错,而是写了但没测——不同 AT 对嵌套 lang 的解析深度不一致,同一段三层嵌套的混排文本,在 NVDA 和 VoiceOver 中表现可能完全不同。



















