lang 属性必须写在 <html> 标签上,因为浏览器、屏幕阅读器、搜索引擎和翻译工具仅以此处值为整页语言依据,决定发音、断词、标点朗读及 :lang() 匹配;写在 <body> 或子元素上无效,会导致 <title> 等关键语义信息语言“失联”。

lang 属性必须写在 <html> 标签上,且只能写一次;写在 <body>、<div> 或任何子元素上,对页面主语言声明完全无效。
为什么只能配在 <html> 上,而不是 <body>
浏览器、屏幕阅读器(如 NVDA、VoiceOver)、搜索引擎和自动翻译工具,全部只读取 <html> 元素的 lang 值作为文档级语言依据。它决定了整页文本的发音规则、断词逻辑、标点朗读方式,以及 CSS 中 :lang() 的匹配起点。
<body lang="zh-CN"> 看似合理,实则被忽略——<head> 里的 <title>、<meta name="description"> 等内容根本不继承 <body> 的 lang,导致这些关键语义信息语言“失联”。
常见错误现象包括:
立即学习“前端免费学习笔记(深入)”;
- 屏幕阅读器把“行”读成 /hæŋ/ 而非 /ʃəŋ/,因为没识别到中文上下文
- Chrome 地址栏不出现翻译按钮,或点击后误判为日语
-
:lang(zh-CN) { quotes: "“" "”"; }完全不生效
lang 值该填 zh-CN 还是 zh-Hans 或 zh
优先用 zh-CN:它是事实标准,覆盖拼音方案、声调模型、词典匹配最全,NVDA/JAWS/VoiceOver 全部稳定支持。
zh-Hans 仅表示“简体字”,不绑定地域,旧版 EdgeHTML 或某些翻译插件可能无法加载对应语音库;zh 过于宽泛,iOS VoiceOver 可能直接 fallback 到英文 TTS 引擎处理多音字。
必须符合 BCP 47 规范,且大小写不敏感但惯例小写。以下全是非法值:
-
zh_china(下划线应为短横线) -
zh-CN(大小写混用虽不报错,但易引发模板拼写不一致) -
Chinese(非标准语言子标签,被静默忽略)
局部多语言内容怎么加 lang
主语言靠 <html lang="zh-CN"> 确立,嵌入的外语内容需显式标注子元素 lang,否则屏幕阅读器仍用中文规则硬读:
- 单个术语:
<span lang="en">API</span>→ 正确读作 /ˈeɪ.piː.ˈaɪ/ - 整段英文:
<p lang="en">This is a code example.</p> - 代码注释:
<pre lang="en"># Initialize counter</pre>(注意不是lang="bash")
避免滥用:<div lang="en"> 包裹多个段落会破坏语义层级,也干扰父级 :lang(zh) 的 CSS 匹配范围。
JS 动态改 document.documentElement.lang 有没有用
基本没用。屏幕阅读器在 DOM 解析初期就读取并缓存了 <html> 的初始 lang 值,后续 JS 修改不会触发语音引擎重载或文本重分析。
如果真要做运行时切换(比如 demo 页),至少做到三件事:
- 同步更新
document.documentElement.lang = "en-US" - 遍历所有已渲染的带
lang的元素(尤其是<body>下的容器),手动重设其lang属性 - 触发
aria-live提示,例如document.getElementById('lang-notice').textContent = 'Language changed to English'
最关键的是:第三方组件(如 Ant Design、Element Plus)内部文案、日期格式、弹窗提示,完全不读取页面 lang,它们依赖自己配置的 locale。光改 <html lang="ja"> 不会让按钮文字变日文——那是组件层的事,和 HTML 语言声明无关。


















