<html lang="zh"> 是语言声明的唯一有效源头,body 的 lang 属性无效且不被浏览器识别;lang 值须符合 BCP 47 规范(如 zh、en),区域子标签需谨慎支持;CSS 按语言加载必须服务端输出或 JS 动态插入 link,不可依赖 [lang] 选择器替代独立样式表。

body 的 lang 属性怎么写才有效
必须和 <html> 标签的 lang 值一致,否则浏览器不识别。只写 body lang="zh" 没用,<html lang="zh"> 才是源头。
常见错误:在 body 上重复设 lang 但没同步 html 标签,或者用错值(比如写 lang="ch" 或 lang="zh-CN" 却没对应样式表)。
-
lang值要符合 BCP 47 规范,推荐用zh、en、ja这类简写;区域子标签(如zh-Hans)需确认浏览器和打包工具支持 - 不要依赖 JS 动态改
body.lang来触发 CSS 加载——CSS 是在 HTML 解析阶段就匹配的,JS 改完已错过时机 - 如果页面多语言靠后端渲染,确保
<html lang="{{locale}}">输出正确;如果是前端切换,得整页重载或用 CSS 变量兜底
如何让不同语言加载不同 CSS 文件
不能靠 <link rel="stylesheet"> 自动按 lang 切换——HTML 没这机制。得手动控制引入逻辑。
最稳的方式是服务端输出时根据语言决定引入哪个文件,比如:
立即学习“前端免费学习笔记(深入)”;
<link rel="stylesheet" href="/css/app-zh.css" media="all">
如果必须前端控制,用 JS 检查 document.documentElement.lang,再动态插入 <link>:
const lang = document.documentElement.lang || 'en';
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = `/css/app-${lang}.css`;
document.head.appendChild(link);
- 注意路径拼接安全,避免
lang值被注入(比如lang="en"><script>alert(1)</script>"),服务端输出更可靠 - 多个语言 CSS 文件建议内容独立,别靠
[lang="zh"]这类选择器覆盖——维护成本高,且无法处理字体、行高、断行等全局差异 - Webpack/Vite 等构建工具下,别把多语言 CSS 打包进同一 chunk,否则用户会白下无用样式
[lang="zh"] 选择器能替代单独样式表吗
能,但只适合小范围微调,比如改个别字间距或引号样式;不适合替换整套排版规则。
原因很实在:中文、日文、阿拉伯文的字体栈、行高基准、标点悬挂、换行逻辑完全不同,全堆在一个 CSS 里,权重冲突、调试困难、体积还变大。
-
[lang="zh"] h1和[lang="ar"] h1写在一起,后期加新语言就得改所有地方 - 某些浏览器对嵌套
[lang]选择器性能不敏感,但大量使用(尤其配合:not()或伪类)会影响首屏渲染速度 - 字体加载行为受
lang影响极小,真正起作用的是font-family中的泛名族(如serif)和系统字体回退链,不是选择器本身
IE 和旧版 Safari 对 lang 的支持要注意什么
IE8+ 和 Safari 5.1+ 都支持 [lang] 属性选择器,但有个关键限制:lang 属性必须出现在 <html> 标签上,body 或其他元素上的 lang 不会被 [lang="xx"] 匹配到(除非显式写成 body[lang="xx"])。
- 不要写
div[lang="zh"]期待它匹配子元素里的文字语言——lang继承自父级,但选择器不自动向上查找 - 旧版 iOS Safari 对
lang值大小写敏感(zh-CN≠zh-cn),统一用小写更稳妥 - 如果你还在支持 IE11,别用
lang控制字体加载,它不支持@font-face的unicode-range+lang联动
body lang 就能触发样式切换」——它只是个静态标记,背后没有魔法。真要分语言加载,得明确谁负责判断(服务端 or JS)、谁负责加载(link 标签 or 动态插入)、谁负责兜底(默认字体 or fallback class)。漏掉任一环,用户看到的就是错位的标点或糊掉的中文字体。








