纯CSS打字机效果需用@keyframes控制width从0%到100%,配合overflow:hidden、white-space:nowrap及等宽字体;JS方案则通过遍历字符数组动态添加文本,避免innerHTML重写与setTimeout嵌套延迟。

用 CSS @keyframes 实现基础打字机效果
纯 CSS 方案最轻量,适合静态文本且不需要交互控制。核心是利用 width 配合 overflow: hidden 模拟逐字显示,再用 @keyframes 控制 width 从 0 到 100% 的过渡。
关键点:必须给容器设固定宽度(或 inline-block + white-space: nowrap),否则 width: 0 → 100% 会撑满父容器而非按文字长度伸展。
常见错误:animation-fill-mode: forwards 忘加,导致动画播完立刻回退;或没设 font-family 等宽字体(如 monospace),导致“打字”节奏错乱。
@keyframes typewriter {
from { width: 0; }
to { width: 100%; }
}
.typewriter {
display: inline-block;
overflow: hidden;
border-right: 1px solid;
white-space: nowrap;
animation: typewriter 2s steps(12, end), blink-caret 0.75s step-end infinite;
}
其中 steps(12, end) 的 12 要手动匹配文字字符数(含空格),否则会出现跳帧或卡顿。
立即学习“前端免费学习笔记(深入)”;
用 JavaScript 实现可配置的逐字输出
需要动态控制、暂停/重播、或内容来自 API 时,必须用 JS。本质是把字符串拆成数组,用 setTimeout 或 requestAnimationFrame 逐个 append。
性能注意:别用 innerHTML +=,每次重写整个 DOM;改用 textContent 或 createTextNode + appendChild。
容易踩的坑:
-
setTimeout嵌套过深可能因事件循环延迟导致节奏漂移,建议用单个定时器 + 索引递增 - 没处理退格(backspace)或光标闪烁逻辑,用户看到的是“堆砌”而非“输入”
- 未考虑中文、emoji 等多字节字符——
str.length对 emoji 可能不准,建议用[...str].length
function typeText(el, text, delay = 100) {
let i = 0;
const chars = [...text];
el.textContent = '';
const timer = setInterval(() => {
if (i < chars.length) {
el.textContent += chars[i++];
} else {
clearInterval(timer);
}
}, delay);
}
光标闪烁与兼容性细节
纯 CSS 光标(border-right)在 Safari 上可能不闪烁,或与文字颜色冲突。更稳的方式是额外加一个 <span class="cursor">|</span> 并单独控制其 opacity 动画。
兼容性影响:
- CSS
steps()在旧版 Edge 不支持,需加-ms-前缀或降级为 JS - Firefox 对
animation-timing-function: steps()的解析略保守,建议显式写steps(12, end)而非steps(12) - 移动端 iOS Safari 有时会禁用非交互元素的 CSS 动画,可在
:hover或:focus-within触发后启用
如果页面有 SSR(比如 Next.js / Nuxt),首次渲染时 JS 还没执行,CSS 方案更可靠;但若需响应 props 变化,则 JS 方案必须配合 useEffect 或 mounted 钩子重新初始化。
要不要加删除(backspace)效果?
多数真实场景需要“输入→停顿→删除→重输”,比如展示 slogan 切换。这时不能只做单向打字,得维护状态机:当前文本、目标文本、是否在删除阶段。
复杂点在于时间控制:打字和删除速度常不同(删除更快),且需在删完后等待再输入下一句。硬编码多个 setTimeout 极易失控,推荐封装成队列:
- 把每轮“输入 A → 等待 → 删除 A → 输入 B”作为一项任务
- 用
Promise+async/await串行执行,避免回调地狱 - 暴露
stop()和restart()方法,方便用户交互中断
真正难的不是实现,而是让节奏自然——人眼对前 0.3 秒的停顿极其敏感,delay 设成 80ms 和 120ms 感知差异巨大,得实测调整。


















