steps() 是打字机效果的唯一合理选择,因其能将动画强制分割为离散帧实现逐字显示,而 ease 或 linear 会导致模糊重叠;需配合 white-space: nowrap、monospace 字体、ch 单位及 step-end 光标动画。

为什么 steps() 是打字机效果的唯一合理选择
因为打字机效果本质是“逐字显示”,不是平滑过渡,animation-timing-function: steps() 能把动画强制切分成离散帧,每步只显示一个字符。用 ease 或 linear 会模糊、重叠、漏字——浏览器根本不会按字符截断渲染,它只按时间插值计算 opacity 或 width,结果就是“渐显一串”,不是“一个一个蹦出来”。
关键点:steps(6, end) 表示把整个动画时长均分为 6 步,且在每步**结束时刻**才跳到下一状态(end 是默认值,可省略;start 会导致首字符延迟出现,通常不用)。
HTML 结构必须用 white-space: nowrap 配合单行容器
如果文字换行或被空格折行,steps() 动画会失效——因为实际要逐字显示的是“视觉上连续的单行字符串”。常见错误是直接对 <p></p> 或 <div> 应用动画,但没控制空白符行为。
<p>实操建议:</p>
<ul>
<li>容器加 <code>white-space: nowrap,防止内部空格/换行符触发折行
或 CSS 控制<span></span> 包裹纯文本,避免块级元素默认样式干扰width: 10em)或 overflow: hidden,否则看不到“逐字展开”的裁剪效果CSS 动画需配合 ch 单位与 monospace 字体
ch 是当前字体中 “0” 字符的宽度单位,对等宽字体(如 font-family: monospace)来说,1ch ≈ 1 个字符宽度。这是精准控制“每步显示一个字符”的物理基础。用 px 或 em 会因字体比例浮动,导致最后几字符错位或截断。
示例核心代码:
.typewriter {
overflow: hidden;
border-right: 2px solid black;
white-space: nowrap;
font-family: monospace;
animation:
typing 3s steps(12, end),
blink-caret .75s step-end infinite;
}
@keyframes typing {
from { width: 0 }
to { width: 12ch }
}
注意:steps(12, end) 中的 12 必须和目标字符串长度一致(本例为 12 字符),且 to { width: 12ch } 也得同步——差 1 就少显或溢出。
光标闪烁必须用 step-end,不能用 linear
如果光标动画用 linear,你会看到光标淡入淡出,像呼吸灯——这不是打字机。真实打字机光标是“开/关”式硬切换。所以必须用 step-end:在周期末尾瞬间切换 visibility 或 border-color。
常见错误:
- 把光标和打字动画写进同一个
@keyframes—— 逻辑耦合,难以单独调试 - 用
opacity做光标,再配合linear,导致半透明残影 - 忘记加
infinite,光标只闪一次就停了
最简可靠写法是独立动画 + border-right 模拟光标,配合 step-end 切换显隐。
字符数动态变化时,steps() 的参数和 width 值必须同步更新——CSS 本身不支持变量计算,这意味着 JS 注入或预编译是绕不开的。手写动画时,数错一个字符,效果就全偏了。











