纯 css 可实现文字逐行渐显;关键用 line-height + clip-path 或 mask 配合 animation 控制显示区域,通过 inset() 上边距从 100% 降至 0 逐步露出各行,总时长按行数均分,避免拆 span 或 opacity 整段闪现。

用 CSS animation 实现文字逐行渐显的最小可行方案
直接给结论:纯 CSS 就能做,不需要 JS;关键不是“逐字”而是“逐行”,得靠 line-height + clip-path 或 mask 控制显示范围,animation 驱动高度变化。用 opacity 或 visibility 只能整段闪现,达不到“逐行”效果。
常见错误是把文本拆成多个 <span></span> 手动加 delay——代码冗余、维护困难、换行响应不一致。真正靠谱的做法是让浏览器按渲染后的行盒(line box)自然分层。
- 必须给容器设固定
line-height和overflow: hidden - 动画目标是让
clip-path的inset()上边距从100%降到0,逐步露出各行 - 动画时长要配合行数:比如 5 行文本,总时长设为
2.5s,每行约0.5s进入
.fade-lines {
line-height: 1.6;
overflow: hidden;
clip-path: inset(100% 0 0 0);
animation: reveal-lines 2.5s forwards;
}
@keyframes reveal-lines {
to { clip-path: inset(0 0 0 0); }
}
Firefox 下 clip-path 不生效?换 mask 方案
clip-path 在旧版 Firefox(inset() 时容易失效。这时改用 -webkit-mask + linear-gradient 更稳妥,且兼容 Chrome/Safari/Firefox 100+。
原理一样:用渐变遮罩从全黑(隐藏)过渡到全白(显示),控制遮罩高度展开。
- mask 图像必须用
linear-gradient(to bottom, #000 0%, #000 50%, #fff 50%, #fff 100%)这种硬切方式,避免模糊过渡 - mask-size 的高度要等于单行高度 × 行数,宽度设为
100% - mask-repeat 设为
no-repeat,mask-position 初始为top,动画中改为bottom
.fade-lines-mask {
line-height: 1.6;
-webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 50%, #fff 50%, #fff 100%);
-webkit-mask-size: 100% calc(1.6em * 5); /* 假设共5行 */
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: top;
animation: mask-reveal 2.5s forwards;
}
@keyframes mask-reveal {
to { -webkit-mask-position: bottom; }
}
动态内容行数不确定时怎么算动画时长?
服务端或 JS 渲染的文本行数不可预知,硬写 calc(1.6em * N) 会出错。这时候不能靠 CSS 纯解,得加轻量 JS 获取实际行数:
- 用
getClientRects()拿到所有行盒,长度就是真实行数:element.getClientRects().length - 避免用
offsetHeight / line-height,因为 padding/border/字体渲染差异会导致计算偏差 - 拿到行数后,动态设置
style.setProperty('--line-count', n),CSS 里用calc(1.6em * var(--line-count)) - 动画总时长建议按
n * 0.4s动态生成,太快看不清,太慢拖节奏
注意:如果文本在 viewport 外或 display: none,getClientRects() 返回空数组,得等元素可见后再执行。
移动端 Safari 卡顿或闪烁?关掉 will-change 并启用硬件加速
iOS Safari 对 clip-path 动画优化差,尤其长文本滚动时容易掉帧。单纯加 will-change: clip-path 反而加重负担,正确做法是用 transform: translateZ(0) 触发 GPU 加速,同时限制重绘区域。
- 给动画容器加
transform: translateZ(0),但别加在伪元素或子元素上,否则可能触发额外合成层 - 避免同时动画
clip-path和opacity,Safari 会降级到 CPU 渲染 - 如果内容区域有背景色,用
backface-visibility: hidden防止 iOS 闪屏 - 测试时打开 Safari 开发者工具 → Rendering → “Paint flashing”,确认只有容器本身在重绘
行数多、字体复杂、设备性能弱时,“逐行渐显”本质是视觉权衡——宁可少几帧,也不能卡住主线程。真要兼顾性能和效果,优先保证首屏 3 行的流畅性,其余延迟加载或简化动画参数。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











