直接用 content + ::after 无法实现流畅打字效果,因 content 不支持逐字符动画且不可过渡;应改用 width 或 clip-path 配合 steps() 控制遮罩,文字写在 HTML 内,光标单独用伪元素实现。
为什么直接用
+
写打字效果会卡顿或跳字
因为
属性本身不支持逐字符动画,CSS 无法对伪元素的内容做“字符串切片”;你看到的所谓“打字”效果,本质是靠
控制
或
做视觉遮罩,不是真正在往里塞字符。如果误以为可以动态改
的值来模拟输入,就会发现它根本不响应动画帧——
是非过渡属性,也不能被
驱动。
实操建议:
用
和
锁定单行显示
动画目标必须是可过渡的属性:优先选
(配合
)或
(更平滑,但 IE 不支持)
文字内容写在 HTML 元素内,不要试图塞进
的
里做动态拼接
若坚持用
,只让它承载光标(如
),而非文字主体
用
+
实现精准逐字节奏
这类缓动函数才是控制“一个字一停”的关键,不是靠时间均分。假设你要打 6 个字,就设
,动画总时长除以 6 才是单字停留时间。用
会滑动模糊,看不出字形。
示例结构:
立即学习
“
前端免费学习笔记(深入)
”;
CSS 片段:
注意点:
使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
下载
是粗略值,实际应按字体和字号测——更稳妥用
:比如
(1ch ≈ 一个 0 的宽度)
中的
必须严格等于字符数(空格也算),否则最后一字闪一下就消失
动画结束后加
,否则
会弹回 0
方案比
更可靠,但要注意兼容性
从右往左裁剪,配合
改变右侧偏移量,能避免字体度量误差,也不依赖
/
估算。但 Safari 旧版、IE 完全不支持,移动端 Android 4.4– 最好降级。
核心写法:
使用条件:
必须确保父容器有
,否则
裁剪会被外层截断
不能和
同时触发硬件加速,否则某些 Chrome 版本会闪烁
想兼容老浏览器?加一层
包裹,并在外部写
备用方案
光标闪烁怎么和打字节奏同步而不抢戏
单独写一个
动画很容易和打字不同步——比如打字结束光标还在狂闪,或者打完字光标立刻消失。正确做法是让光标动画时长 = 打字总时长,并用
控制闪烁时机。
关键参数:
光标动画周期设为打字总时长的约 1/4~1/3(例如打字 3.2s,光标用 0.75s),并
必须用
,否则透明→不透明过程会渐变,失去“数字终端”感
如果打字动画用了
,光标要额外加
来等文字打完再开始稳定闪烁
别用
模拟光标——它会随字体变化抖动;推荐用
或绝对定位伪元素
真正难调的是多行文本场景:每行字数不同,
数量就得分别算,没法共用一套动画。这时候不如交给 JS 控制,CSS 只负责光标和基础入场。
content::aftercontentkeyframeswidthclip-pathcontentcontent@keyframeswhite-space: nowrapoverflow: hiddenwidthinline-blockclip-path::aftercontent::aftercontent: "|"widthsteps()steps(6, end)steps(6, end)linearHello World.typewriter {
font-family: monospace;
white-space: nowrap;
overflow: hidden;
border-right: 2px solid #000;
width: 0;
animation:
typing 3.2s steps(11, end),
blink-caret .75s step-end infinite;
}
@keyframes typing {
from { width: 0 }
to { width: 11em } /* 手动估算字符宽度,或用 ch 单位 */
}
@keyframes blink-caret {
from, to { border-color: transparent }
50% { border-color: #000 }
}11emchwidth: 11chsteps(11, end)11animation-fill-mode: forwardswidthclip-pathwidthclip-path: inset(0 100% 0 0)animationemch@keyframes clip-typing {
from { clip-path: inset(0 100% 0 0) }
to { clip-path: inset(0 0 0 0) }
}
.typewriter-clip {
clip-path: inset(0 100% 0 0);
animation: clip-typing 3.2s steps(11, end) forwards;
}overflow: visibleclip-pathtransform@supports (clip-path: inset(0)) { ... }widthblink-caretstep-endinfinitestep-endforwardsanimation-delay: 3.2sborder-rightbox-shadowsteps()