可用CSS变量--char-count和--duration控制打字机效果:前者决定steps()步数与最终宽度(calc(var(--char-count) * 1ch)),后者设定总时长;必须用steps(N, end)配合ch单位实现逐字卡顿显示,且字符数变化时需强制重播动画。

如何用 CSS 变量控制打字机效果的字符数和持续时间
打字机效果本质是控制 animation 的关键帧进度,而字符数量与时长直接决定动画节奏。纯 CSS 实现的关键在于:**不能靠 JS 动态改 @keyframes,必须把变化逻辑“编译”进变量驱动的动画参数中**。
核心思路是用 --char-count 控制总字符数(影响 width 和 steps()),用 --duration 控制总时长(影响 animation-duration)。但注意:CSS 无法直接用变量做除法算单字符耗时,所以得用 steps() + 固定总时长来反向模拟逐字效果。
为什么 steps() 是必须的,且步数要等于字符数
steps() 是实现“卡顿式”逐字显示的唯一可靠方式。浏览器对 animation-timing-function: steps(N) 的解释是:把整个动画过程均分为 N 步,每步瞬间跳变,无过渡。
若文本有 12 个字符,设 steps(12),再配合 width 从 0ch 到 12ch 的线性变化,就能让每一帧刚好显示前 N 个字符。一旦 steps() 值与实际字符数不一致,就会漏字、多字或卡住。
立即学习“前端免费学习笔记(深入)”;
- 字符数变化时,
--char-count必须同步更新,否则steps()失效 - 不能用
steps(1)配合 JavaScript 每帧改width—— 这会触发重排,性能差且不同步 -
ch单位比em或px更稳,因它基于 “0” 字符宽度,等宽字体下 1ch ≈ 1 字符
完整可复用的 CSS 声明块(含变量校验逻辑)
以下代码支持任意字符数和总时长,且已规避常见陷阱:
.typewriter {
overflow: hidden;
white-space: nowrap;
width: 0;
animation: typewriter var(--duration, 3s) steps(var(--char-count, 10), end) forwards;
}
<p>@keyframes typewriter {
to {
width: calc(var(--char-count, 10) * 1ch);
}
}使用时只需在元素上设置两个内联变量:
<div class="typewriter"
style="--char-count: 7; --duration: 2.1s">Hello!</div>注意点:
-
steps(N, end)中的end很关键:它让第 N 步才完成最终宽度,避免最后一帧闪回 -
calc()里直接乘1ch,而非写死7ch,保证变量生效 - 若内容含空格或中文,需确保字体为等宽(如
font-family: monospace),否则ch计算偏移 - IE 不支持
ch单位,如需兼容,得 fallback 到em并手动测比例(例如1em ≈ 0.6ch)
动态切换时为什么不能只改变量,还得重置动画
直接修改 --char-count 或 --duration 不会自动重启动画 —— CSS 动画只在属性首次计算或 animation-name 改变时触发。所以想“重新打字”,得强制重播:
- 最简方案:用 JS 切换一个临时类名,比如
typewriter--play,并在该类里定义动画,切换时先remove再add - 更稳妥方案:用
animation-play-state: paused+void offsetHeight强制重绘,再设回running - 绝对不要用
animation: none瞬间清空再恢复 —— 会导致 DOM 宽度突变为 0,视觉闪烁
变量本身很轻量,但动画重播逻辑稍重;如果频繁切换,建议用 requestAnimationFrame 节流,或干脆改用 Canvas 实现高帧率场景。


















