应使用css动画+等宽字体栈+ch单位实现打字机效果,因标签已废弃、无语义、不支持动画、可访问性差且字体渲染不可控。

别用 <tt></tt> 标签实现打字机效果——它已废弃,且根本不能可靠控制“打字”动画,只能勉强撑出等宽字体。 真正要实现逐字显现的打字机效果,必须靠 CSS 动画 + 等宽字体 + 字符宽度单位(ch)协同控制,<tt></tt> 连基础排版都语义错位,更别说动画逻辑。
为什么 <tt></tt> 根本不能做打字机效果
<tt></tt> 只是一个纯样式标签,HTML5 明确标记为 obsolete。浏览器渲染它仅出于兼容容忍,不保证行为一致:
- 它没有语义,屏幕阅读器完全忽略,对可访问性零支持
- 它不参与任何 CSS 动画触发机制——
width、opacity、clip-path对它都不起作用,除非你额外套一层容器 - Lighthouse、axe 等工具会直接报 error,CI/CD 流程可能因此失败
- 它的默认样式只是
font-family: monospace,但连这个都不是规范强制,而是浏览器“顺手加的”
font-family: monospace 必须显式设置,且不能只写 monospace
打字机效果依赖每个字符视觉宽度严格一致,而 monospace 是通用关键字,不同系统 fallback 差异极大:
- Windows 上可能映射到 Courier New(偏粗、字距松)
- macOS 可能用 Menlo(偏细、字距紧),导致
12ch实际像素宽度偏差 ±8px - Linux 下可能是 DejaVu Sans Mono,连连字处理都不同
正确写法是明确指定字体栈,并以 monospace 收尾保底:
.typewriter {
font-family: 'Fira Code', 'Source Code Pro', 'Consolas', monospace;
font-variant-ligatures: none; /* 防止 fi/fl 连字破坏 ch 计算 */
}
打字机动画必须用 width + steps() + ch 单位
这是目前唯一能在 Chrome、Firefox、Safari 中稳定按字符步进的方案。关键不是“让字出来”,而是“裁剪可见区域并卡帧推进”:
- 文字必须完整写死在 HTML 中,不能靠 JS 拼接或伪元素生成(否则无法精确计数)
- 容器需设
display: inline-block或block,white-space: nowrap,overflow: hidden - @keyframes 中
width必须从0ch到Nch(N = 字符总数,含空格) -
animation中steps(N, end)的N必须与字符数完全一致,少 1 就丢最后一个字 - 若文本含中文或 emoji,
ch单位会失效(它们不是等宽),此时应改用 JS 方案或手动拆分<span></span>
光标闪烁必须用 border-right 或 box-shadow,不能靠伪元素模拟
很多教程用 ::after 做光标,但在 Safari 和旧版 Firefox 中易出现定位漂移或动画撕裂:
- 推荐用
border-right: 0.1em solid currentColor直接附着在文本容器右侧 - 动画用
@keyframes blink-caret { 50% { border-color: transparent; } },配合step-end避免频闪 - 注意
border-box盒模型:如果容器有padding,需用calc(100% - padding)校准width终点,否则光标错位 - 移动端需加
-webkit-transform: translateZ(0)强制 GPU 加速,防止光标卡顿
真正难的不是写出第一版打字机,而是让它在中英文混排、响应式缩放、深色模式切换、以及读屏软件聚焦时都保持字符对齐和节奏稳定——这些细节里,<tt></tt> 连入场券都没有。










