ch单位最适合打字机动画,因其等于当前字体中“0”的宽度,等宽字体下每字符占1ch,确保逐字精准显现;而em受字符形状影响、px脱离字体上下文。

为什么 ch 单位比 em 或 px 更适合打字机效果
因为 ch 表示“0”字符的宽度(即当前字体中数字零的水平尺寸),它天然适配等宽字体下的单字符宽度,而打字机效果本质是逐字显示,每步前进距离必须严格对齐字符边界。用 px 会因字体缩放、DPR 变化失准;用 em 依赖 font-size 缩放,但不保证等宽——只有 ch 能让 steps() 的每一步精准落在字符右边缘。
实操建议:
- 务必在
monospace字体栈中使用,例如font-family: 'Fira Code', 'JetBrains Mono', monospace - 避免在
font-variant-numeric: tabular-nums关闭时混用比例数字,否则ch值可能浮动 - 若内容含中文或全角字符,
ch不适用——此时应改用 JS 驱动或放弃纯 CSS 方案
steps() 的起始方向与步数怎么算才不漏字
steps(n, start) 中的 n 必须等于文本字符数,start 必须显式写上,否则默认 end 会导致第一帧就显示全部内容(浏览器把“从 0% 到 100% 分 n 步”理解为“第 1 步结束时跳到 1/n”,而非“第 0 步显示前 0 个字符”)。
常见错误现象:steps(5) 动画一播放就全显示,或最后一个字符始终不出现。
立即学习“前端免费学习笔记(深入)”;
正确写法示例:
animation: type 3s steps(12, start) forwards;
说明:
- 字符串长度为 12,
steps(12, start)才能确保第 0 帧显示 0 字符,第 1 帧显示第 1 字符,……第 12 帧显示全部 12 字符 - 用
getBoundingClientRect().width / getComputedStyle(el).fontSize算出近似字符数不可靠,必须硬编码或服务端注入真实长度 - 动态内容?别硬套纯 CSS——
steps()不支持运行时重算步数
如何用 ch 控制宽度并隐藏溢出文字
打字机不是靠 opacity 渐变,而是靠容器宽度从 0ch 拉伸到 Nch,再配合 overflow: hidden 实现“逐字推出”效果。关键在于:宽度动画必须用 ch,且初始值为 0ch,终值为精确字符数 × ch(比如 12 字符就写 12ch)。
容易踩的坑:
- 写成
width: 12ch但父容器有padding或border,导致实际可渲染宽度不足——需用box-sizing: border-box - 动画用
width会触发重排,性能差;更优解是用transform: scaleX()+origin-left,但此时无法用ch,得换算成小数(如 12 字符 →scaleX(1),6 字符 →scaleX(0.5)) - 行内元素(如
span)默认不响应width,必须设display: inline-block或block
兼容性与降级方案:哪些浏览器会掉链子
ch 单位在 IE 完全不支持,iOS Safari steps() 的 start 关键字在 Safari 14.1 之前只支持 end。这意味着纯 CSS 打字机在旧环境大概率直接失效为“全量显示”。
务实做法:
- 加
@supports (width: 1ch) and (animation-timing-function: steps(1, start))包裹动画规则 - 不加
forwards的动画在结束后会回退,文字消失——这是最常被忽略的细节 - 真要保低版本?用
visibility: hidden+ JSsetTimeout逐字符插入,别硬撑 CSS
复杂点在于:字符数、字体度量、容器约束三者必须严丝合缝,差 0.1ch 或少 1 步,效果就断在中间。别指望“差不多就行”。


















