::first-letter对中文无效,因其仅识别Unicode字母类(Lu/Ll/Lt)字符,而汉字属Lo类,主流浏览器引擎不支持;替代方案包括服务端注入span、CSS initial-letter(新浏览器)和JS动态包裹。

::first-letter 对中文字符不按“首字”逻辑生效,而是按 Unicode 字符分类和浏览器排版引擎规则处理
为什么中文“首字”常被跳过或识别异常
根本原因在于 ::first-letter 并非“取第一个可见字符”,而是依据 CSS Text Level 4 规范,只对 Unicode 类别为 Lu(大写字母)、Ll(小写字母)、Lt(首字母大写)的字符触发。中文汉字属于 Lo(Other Letter)类,主流引擎(Blink/WebKit)默认不将其纳入 ::first-letter 作用范围。所以写 p::first-letter { text-transform: uppercase; } 对中文段落完全无效——不是 bug,是规范行为。
哪些中文场景下 ::first-letter 实际会生效
它确实可能“动”到中文内容,但条件苛刻且不可控:
- 首字符是中文标点,如
《、【、"、「等——这些属于Pc(标点,连接)或Po(标点,其他),部分浏览器会将其与后紧跟的汉字一并捕获(例如《春》的::first-letter可能是《,也可能是《春) - 首字符是阿拉伯数字或罗马数字(如
1. 概述中的1),此时::first-letter会选中该数字,但text-transform无视觉变化 - 某些旧版 Firefox 曾将全角标点(如
?)视为有效首字符,而 Chrome 则跳过——跨浏览器表现不一致
font-size 放大后文字错位、截断或重叠的根源
即使首字被成功选中(比如开头是 【 或纯汉字在某浏览器下侥幸命中),放大后极易出问题:
立即学习“前端免费学习笔记(深入)”;
-
line-height若未显式设置为无单位值(如0.75),会继承父级计算后的绝对高度,导致首字行框挤压后续文字 - 中文方块字形天然占据更大 inline-box,
float: left后若line-height太小(如0.6),字形会被裁切;太大(如1.2)则第二行上移压住首字 - 不同中文字体对同一字号的 baseline、ascent/descent 渲染差异极大,用
margin-top或vertical-align微调几乎无效,反而破坏流式对齐
别信“中文支持 ::first-letter”的模糊说法
网上有些资料说“中文也能用”,其实是混淆了现象和机制:
- 你看到某个汉字变大了,大概率是因为它前面没有空格/换行/注释,且浏览器恰好把该汉字当作首个格式化字符(非规范保证,属实现偶然)
- CSS
initial-letter(Chrome 117+ / Safari 16.4+)虽支持中文首字占多行,但它不改变大小写,也不触发text-transform,且依赖字体 OpenTypecase特性——目前几乎没有中文字体提供该特性 - 真正稳定可控的方式仍是服务端注入
<span class="first-char">春</span>或 JS 动态包裹,但要注意避免破坏已有内联结构(如<em>、<a>)和 SSR 渲染时机
最易被忽略的一点:哪怕你在本地测试时一切正常,CMS 输出的段落开头带空格、换行、HTML 注释或富文本标签(如 <strong>你好</strong>),都会让 ::first-letter 静默失效——上线前必须用真实数据验证首字符上下文。


















