:lang() 伪类仅匹配带正确 lang 属性的元素,真正控制字体的是后续 font-family 声明;生效前提是 html 中 lang 属性显式、非空、符合 bcp 47(如 zh-cn),且中日韩需分开声明字体、西文字体置后、混合内容须为内联元素设 lang。

:lang() 伪类本身不切换字体,它只是匹配带 lang 属性的元素;真正起作用的是你写在它后面的 font-family 声明——但绝大多数“没生效”问题,根源不在 CSS 写法,而在 HTML 的 lang 属性压根没设对或设得不精确。
HTML 的 lang 属性必须显式、非空、符合 BCP 47
浏览器完全不推断语言,也不读取系统 locale 或 Accept-Language。以下全是无效写法:
-
(没lang) -
(空值) -
或(非法标签) -
(只认lang,xml:lang在 HTML5 中不触发:lang())
正确写法示例:
大小写不敏感(zh-cn 和 zh-CN 都行),但下划线格式(如 zh_CN)不被识别。
:lang(zh) 和 :lang(zh-CN) 匹配逻辑不同,别混用
:lang(zh) 是前缀匹配:能命中 lang="zh"、lang="zh-CN"、lang="zh-TW",但 Safari 某些版本对子标签解析更严格,:lang(zh) 可能不触发,而 :lang(zh-CN) 稳定生效。
- 想覆盖所有中文变体 → 同时写多个:
html:lang(zh), html:lang(zh-CN), html:lang(zh-TW), html:lang(zh-HK) - 要精确控制简体中文 → 直接用
:lang(zh-Hans),但前提是你的真这么写了 - 别写
:lang("zh")(引号多余)或:lang(zh-cn)(小写没问题,但括号内值必须和属性值结构一致)
字体声明顺序错了,中英文都会翻车
直接写 font-family: "Noto Sans CJK SC", sans-serif 是典型错误:西文字母会被强制套用中文字体,导致字重发虚、标点错位;更糟的是,若用户系统没装该字体,sans-serif 会回退到 Helvetica(macOS)或 Arial(Windows),而这俩对日文、韩文支持极差,结果就是方块。
- 中日韩必须分开声明:
:lang(zh) { font-family: "SF Pro SC", "PingFang SC", sans-serif; }、:lang(ja) { font-family: "Hiragino Kaku Gothic Pro", "Yu Gothic", sans-serif; } - 西文字体必须放在 CJK 字体之后,否则会被覆盖;
sans-serif或system-ui必须放在最后兜底,绝不能放最前 - 混合内容(如
<p>Hello世界</p>)需在内联元素上加lang:<span lang="en">Hello</span><span lang="zh">世界</span>,再用span:lang(en)/span:lang(zh)单独控制
动态改 lang 属性后样式不更新?不是 bug,是预期行为
CSS 不监听 DOM 属性变更。document.documentElement.lang = "ja" 执行后,样式不会自动重算。
- 简单粗暴法:触发重排,例如
document.body.offsetHeight(读取一个布局属性) - 稳妥做法:配合 class 切换,比如同时改
lang和加lang-ja类,CSS 写成html.lang-ja :lang(ja),避免纯依赖属性变更 - 预加载关键字体:用
<link rel="preload" as="font">提前加载:lang(ja)对应的@font-face,避免切换后字体闪动
最容易被忽略的,是把全部希望押在 上,却忘了混合内容必须为每个语言片段显式标注 lang——没有它,:lang() 就是透明的。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











