::first-letter对中文无效,因其仅识别unicode字母类字符(lu/ll/lt),而汉字属lo类,主流引擎不支持;替代方案有服务端注入span、css initial-letter(新浏览器)和js动态包裹。

为什么 ::first-letter 对中文段落无效
因为 ::first-letter 是 CSS 规范中明确定义为“选择一个块级元素中**第一个格式化字符的首字形**”的伪元素,它只对字母、数字、标点等 Unicode 字母类字符(Lu、Ll、Lt 等)生效,而中文汉字属于 Lo(Other Letter)类,在多数浏览器引擎(如 Blink、WebKit)中不被识别为可被 ::first-letter 选中的“首字母”。所以给 p 写 p::first-letter { text-transform: uppercase; } 对中文段落完全没反应。
::first-letter 实际生效的边界条件
它不是简单取“第一个字符”,而是依赖 CSS Text Level 4 的“首字母提取规则”:必须是排版上独立成形、且能参与大小写变换的字符。常见有效场景包括:
- 英文段落开头是英文字母(
A、b、ß)、带重音的拉丁字母(é、ñ) - 开头是数字(
1、Ⅱ),但此时text-transform: uppercase无视觉变化 - 开头是某些标点(如
"、'、(),且后紧跟字母——这时会连同标点一起被选中(例如"Hello"的::first-letter是"H) - 开头有空格、换行或
?会被跳过,直到找到首个符合条件的字符
注意:::first-letter 不支持选择多个字符(如 ch 在德语中不算单个字形),也不支持对 display: inline 元素使用。
中文首字大写的三种可行替代方案
没有浏览器原生支持中文 ::first-letter,只能靠其他方式模拟。优先级按实用性排序:
- 服务端/构建时注入
<span class="first-char">你</span>好世界,再用.first-char { font-size: 1.4em; line-height: 0.8; float: left; }手动实现“首字下沉+放大”,最稳定 - CSS
initial-letter(Chrome 117+、Safari 16.4+ 支持):写p { initial-letter: 2; }可让首字占两行高,但它不控制大小写,且对中文仅当字体支持 OpenTypecase特性时才可能影响形态(实际几乎无效果) - JavaScript 动态包裹:用
el.innerHTML = el.textContent.replace(/^(\S)/, '<span class="cap">$1</span>');,但要注意避免破坏已有 HTML 结构、脚本执行时机、以及 SSR/SEO 风险
别碰 text-transform: capitalize——它只对空格分隔的单词首字母生效,对中文整个段落毫无作用。
容易被忽略的兼容性陷阱
::first-letter 在不同浏览器中对“首字母”的判定并不一致。例如:
- Firefox 会把
«Bonjour»中的«当作::first-letter一部分,Chrome 则只取B - 如果段落开头是
<img>或<svg></svg>,部分旧版 Safari 会崩溃或跳过该伪元素 -
font-variant-caps: small-caps和::first-letter组合在 iOS Safari 中可能失效 - 使用
letter-spacing或word-spacing后,::first-letter的尺寸计算可能意外偏移
真要保底控制首字样式,别依赖伪元素是否“聪明”,老老实实加一层 DOM 节点最省心。











