steps()是打字机动画的关键,因其将动画分割为离散步进、不插值不过渡,精准模拟逐字敲击;需配合monospace字体、ch单位及steps(n,end)中n等于字符数(含空格)才能稳定实现。

为什么 steps() 是打字机动画的关键
CSS 动画默认使用缓动函数(如 ease),文字会“滑入”或“渐显”,无法模拟逐字出现的机械感。而 steps() 是唯一能强制动画在指定帧数内跳变式前进的时序函数——它把整个动画过程切成离散步进,不插值、不过渡,正好匹配“一个字符接一个字符敲出来”的行为逻辑。
- 必须配合
monospace字体(如Consolas,Roboto Mono),否则字符宽度不等会导致闪烁或错位 -
steps(N, end)中的N应等于目标文本的字符数(含空格),end表示每步在区间末尾触发(更符合打字节奏) - 若用
start,第一帧就会显示第一个字符,失去“光标等待”效果
如何用 ch 单位 + width 实现逐字展开
打字机效果本质是控制容器宽度从 0ch 逐步撑开到完整文本宽度。这里必须用 ch(1ch = 当前字体中 “0” 的宽度),而非 em 或 px,因为只有 ch 能随等宽字体严格对齐字符数。
.typewriter {
width: 0;
white-space: nowrap;
overflow: hidden;
border-right: 1px solid #000; /* 模拟光标 */
animation: typing 3s steps(12, end), blink 0.75s step-end infinite;
}
@keyframes typing {
from { width: 0ch; }
to { width: 12ch; } /* 必须和 steps(12, end) 中的 12 一致 */
}
- 文本内容必须是纯字符串(无换行、无 HTML 标签),否则
ch计算失效 - 若文本含中文,需确认字体对中文字形也按等宽渲染(如
Fira Code不支持中文等宽,Source Code Pro更稳妥) - 动画时长除以
steps()步数,就是单字符停留时间(如3s / 12 = 0.25s),可据此反推节奏
如何让光标在打字结束后继续闪烁
单纯用 animation: typing, blink 并不能保证光标在打字停住后持续闪烁——因为 typing 动画结束后,width 固定,但 blink 若未设置独立循环规则,可能同步结束或错相。
-
blink动画必须单独声明infinite和step-end,且起始状态设为透明(避免首帧突显) - 边框颜色用
currentColor可继承文字色,避免硬编码 - 光标动画延迟应略大于打字动画时长(如打字 3s,光标
animation-delay: 3s),确保它只在打完才开始闪
@keyframes blink {
50% { border-color: transparent; }
}
遇到文字截断或光标错位怎么办
最常见问题是容器父级有 padding、flex 布局干扰,或文本节点被 Vue/React 的空格处理机制压缩。
- 检查开发者工具中元素实际渲染宽度是否等于
Nch(右键“检查” → “Computed” → 查width) - 确保文本外层无
text-overflow: ellipsis或min-width覆盖 - React 中用
{"text"}而非text防止 JSX 自动合并空白;Vue 中用v-pre或white-space: pre保留空格 - 如果光标始终偏左/偏右,大概率是字体加载未完成就执行动画——加
@font-face的font-display: swap或监听document.fonts.load后再触发动画
这种效果的脆弱点不在写法本身,而在字体度量与 DOM 渲染时机的耦合。哪怕多一个空格、少一次重排,都可能让 steps() 的离散步进踩空。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











