steps() 是实现打字机效果的关键,它将 width 动画分割为离散帧,配合 overflow: hidden 和 white-space: nowrap 实现逐字显现;ch 单位适用于等宽字体,中英文混排时需调整步数或改用 monospace 字体。

为什么 steps() 是打字机效果的关键
CSS 动画里用 linear 或 ease 拉宽度,文字是“滑”出来的,不是“一个字一个字蹦”出来的。真正模拟打字节奏得靠 steps() —— 它把动画切成离散帧,每帧只显示固定字符数对应的宽度,不插值、不过渡。
-
steps(5, start)表示分 5 步完成,第一步立刻显示第 1 步结果(即首字符宽度),适合从 0 开始逐字展开 -
steps(5, end)是最后一步才显示最终态,中间全黑,基本不用 - 步数必须和字符数严格对应;字符数变,
steps()参数就得重算,硬编码容易崩
常见错误:写成 steps(10) 却只显示 6 个字 → 后 4 步空转,末尾留白或卡住
width 动画 + overflow: hidden 的最小可行组合
打字机本质是「控制可见宽度」,不是改内容。所以得靠容器裁剪 + 宽度渐变实现,而不是操作 content 或反复 innerHTML。
- 必须给文字容器设
white-space: nowrap,否则换行会破坏宽度计算逻辑 - 容器需
overflow: hidden,不然宽度撑开时文字直接溢出,看不到“逐字出现”感 - 动画目标是
width从0到fit-content或具体像素值;但fit-content无法参与 CSS 动画,得提前量好最大宽度
.typewriter {
width: 0;
white-space: nowrap;
overflow: hidden;
animation: type 2s steps(12, start) forwards;
}
@keyframes type {
to { width: 12ch; } /* 12 个字符宽度,ch 单位比 px 更稳 */
}
注意:ch 单位比 px 更可靠——它按当前字体的 “0” 字宽计算,等宽字体下 1ch ≈ 1 字符,变字体也不易错位
中英文混排时 ch 失效怎么办
ch 在等宽字体下才准;一旦用 font-family: "PingFang SC", "Helvetica Neue" 这类混合字体,中文字符实际占 2ch 甚至更多,steps(10) + 10ch 就会漏字或截半。
- 最稳妥是用
monospace全局兜底:font-family: "SF Mono", "Consolas", monospace - 或者放弃
ch,改用em配合字体度量:先用getComputedStyle读font-size,再乘以字符数估算(仅限 JS 辅助场景) - 纯 CSS 方案:对中文多的文本,手动调高
steps()步数和width值,比如 8 个汉字 → 用steps(16)+16ch试出来
别信“用 letter-spacing 微调就能对齐”——它只影响间距,不改变单字渲染宽度,治标不治本
动画结束后光标闪烁怎么加
纯 width 动画停在终点就静止了,真实打字机还有竖线光标在闪。这得额外一层伪元素 + 独立动画。
- 用
::after生成光标,position: absolute叠在文字末尾 - 宽度设
1px或0.05em,高度拉满,背景色和文字一致 - 关键:光标动画不能和打字动画共用
forwards,否则它也会停在最后一帧;得单独设infinite和step-start保证闪烁不丢帧
.typewriter::after {
content: '';
position: absolute;
right: -2px; /* 微调位置,避开文字边缘锯齿 */
top: 0;
bottom: 0;
width: 0.05em;
background: currentColor;
animation: blink 0.8s step-start infinite;
}
@keyframes blink {
50% { opacity: 0; }
}
容易被忽略的是:如果容器用了 transform: translateZ(0) 或其他触发层叠上下文的属性,::after 可能被盖住——得确保它的 z-index 足够高,或者干脆去掉那些不必要的硬件加速声明
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











