html的lang属性必须写在根元素上,否则浏览器无视——影响SEO、翻译、字体回退和屏幕阅读器;局部多语言需显式声明lang,CSS应优先用:lang()实现继承匹配。

lang属性不写在上,浏览器根本无视主语言
根元素html的lang属性是浏览器识别整页语言的唯一依据——写在body、div或任意其他标签上,对SEO、自动翻译、字体回退、屏幕阅读器发音全无效。Chrome 会直接跳过整页翻译提示;VoiceOver 按系统默认语种朗读,哪怕页面全是中文;CSS 的hyphens: auto也完全不触发。
常见错误现象:
-
<body lang="zh-CN">——浏览器当没写 - SPA 切换语言后只改
document.body.lang,语音仍用旧语种读 - 服务端渲染漏掉
html标签的lang,首次加载时所有本地化行为都失效
实操建议:
- SSR 页面:根据
Accept-Language头或 URL 路径(如/ja/)动态生成<html lang="ja-JP"> - 静态页:每个语言版本单独一份 HTML,
lang值硬编码,避免 JS 注入延迟导致闪动 - 检查方法:DevTools → Elements → 点击
html节点,确认lang属性存在且值合法
局部多语言内容必须显式声明lang,不能靠继承
浏览器不会推断「这段英文是引用」「这行 Bash 是命令」——它只认你明写的lang。不加,就全按html的lang处理,后果是日文假名用中文字体显示、法语重音错读、拼写检查关闭。
立即学习“前端免费学习笔记(深入)”;
使用场景举例:
- 中文文档里嵌法语引文:
<blockquote lang="fr">Je suis français.</blockquote> - 技术文档夹代码术语:
<code lang="en">useState</code>,触发 IDE 英文高亮 - 命令行示例:
<pre lang="bash">curl -X POST</pre>,lang="bash"虽非 BCP 47 标准,但被语法高亮工具和浏览器识别为代码上下文
容易踩的坑:
当代理已经知道网站路由或内容URL,并且在启动前需要有效的sitemap XML、sitemap索引或robots.txt引用时,请使用sitemap。这是一个发布构件技能,而不是爬虫或SEO平台。
- 给每个单词都加
lang:DOM 体积增大,可访问性树构建变慢 - 误以为
lang="ja"足够:iOS VoiceOver 某些版本降级为英语发音,lang="ja-JP"更稳妥 - 后端返回
zh_ch或ZH-CN,前端没转成小写+连字符,导致lang值非法被忽略
:lang()伪类和[lang]属性选择器行为完全不同
想用 CSS 控制不同语言的排版(比如日文标点间距、阿拉伯文右对齐),结果样式没生效?大概率是选错了选择器。
[lang="ja"]只匹配显式写了lang="ja"的元素,不继承;:lang(ja)能匹配该元素或其任意祖先有lang="ja",适合处理嵌套文本。
实操建议:
- 控制整段外文排版(如英文参考文献):
section[lang="en"] { text-align: left; } - 处理混排中的单个词(如中英术语对照):
p:lang(en) { font-family: "Inter", sans-serif; } - 注意:CSS
:lang()不依赖元素是否实际渲染,只要 DOM 中有对应lang值就生效
SPA切换语言时,只改document.documentElement.lang远远不够
调用document.documentElement.lang = "ko"后,新渲染的内容能读对,但已存在的 DOM 节点(尤其是富文本、第三方组件插入的内容)仍按旧lang解析。屏幕阅读器、拼写检查器、字体引擎全按每个元素自身的lang值工作,不是看父级继承来的。
实操建议:
- 语言切换钩子中,不仅要更新
document.documentElement.lang,还要遍历并重设所有含语言信息的节点,比如<blockquote lang="fr">、<code lang="python"> - 如果用了
data-i18n+ JSON 翻译方案,记得重刷这些节点的textContent,否则lang值虽对,内容还是中文 - 第三方富文本编辑器(如 TinyMCE、Quill)插入的内容,需监听其输出并手动补
lang属性
最常被忽略的点:lang 值必须严格符合 BCP 47。写成zh_CN、chinese或zh这种宽泛值,会导致字体回退异常、拼写检查关闭,甚至某些 SSR 框架拒绝渲染。


















