steps(n, end)是实现逐字打字机效果的关键,它将动画分割为n个离散步,每步在结束时刻跳变显示一个字符,需配合字符数动态设置n并指定end参数确保精准同步。

为什么 steps() 是打字机效果的关键
CSS 动画里用 width 或 clip-path 做打字机,如果直接用 ease 或 linear,文字会“滑”出来,不是逐字显现。而 steps(1, end) 强制动画在每一帧只跳变一次——相当于把整个动画切成 N 个离散步,每步只显示一个字符宽度。这不是视觉错觉,是真正靠时间分片控制渲染节奏。
-
steps(1, end)表示:整个动画时长内只执行 1 次跳变,且跳变发生在该步结束时刻(即最后一帧才生效) - 要实现“逐字”,得配合字符数动态设
steps(N, end),N 就是文字长度 - 错误写法:
steps(1)缺少第二个参数,部分浏览器会 fallback 到start,导致第一字符延迟一帧才出现
用 width + overflow: hidden 最简实现
适合单行、等宽字体场景,兼容性好(IE10+),但对非等宽字体或换行文本不友好。
- 元素需设
display: inline-block或inline-flex,否则width动画无效 - 必须显式设置
white-space: nowrap,否则空格或连字符可能提前折行破坏节奏 - 动画起点
width: 0,终点width: 100%,但实际生效依赖父容器宽度或fit-content行为 - 示例关键片段:
span.typewriter { display: inline-block; overflow: hidden; white-space: nowrap; width: 0; animation: type 3s steps(12, end), blink .75s step-end infinite; } @keyframes type { to { width: 100%; } }
更健壮的方案:用 ch 单位 + steps() 精确控制
ch 单位代表 “0” 字符的宽度,对等宽字体天然适配;配合 steps(N, end) 可避免因父容器缩放、字体加载延迟导致的宽度计算偏差。
- 先用 JS 读取文本长度:
el.textContent.length,再动态写入style.setProperty('--char-count', N) - CSS 中用:
width: calc(var(--char-count) * 1ch),动画从0到该值 - 不要直接在
@keyframes里写calc(),必须用自定义属性传入 - 注意:中文字体下
ch不可靠(“中文”和“0”的宽度常不等),此时应改用monospace字体栈或测出平均字符宽度
常见翻车点:光标闪烁不同步、动画卡顿、多行失效
打字机动画常被当成“小效果”忽略细节,但实际线上最容易暴露问题。
- 光标动画(
border-right或::after)必须和打字动画共用同一animation-timing-function,否则看起来像脱节 - 在低性能设备上,
width动画触发布局重排,比clip-path或transform: scaleX()更卡;后者推荐加will-change: transform - 多行文本不能靠
width实现,得切分 DOM 或用line-clamp+steps()控制行数,但会丢失逐字粒度 - Safari 对
steps()的子帧处理有 bug:当动画时长不能被步数整除时,最后一帧可能跳过;稳妥做法是让时长 ÷ 步数 = 整数毫秒(如 3000ms / 15 = 200ms/step)
事情说清了就结束。真正难的不是写出第一个打字机,而是让第 17 个不同长度、不同字体、不同容器宽度的实例都保持节奏一致——这时候你才会反复看那行 steps(N, end) 里的 end 到底有没有写错。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











