苹果官网文字逐行浮现效果核心是scroll-timeline+opacity,由浏览器原生驱动;transition仅支持一次性淡入,无法响应持续滚动进度。

苹果官网那种文字随滚动“逐行浮现”的效果,核心不是靠 JS 算 scrollTop,而是用 scroll-timeline + opacity 绑定滚动进度,由浏览器原生驱动——既顺滑,又不卡顿。
为什么不能只用 transition + opacity
因为 transition 是时间驱动的:它依赖 CSS 类切换或伪类触发,只能做“一次性的”淡入(比如页面加载后 200ms 显示),无法响应持续滚动。而苹果式效果是「滚动多少,显示多少」,必须把动画进度和滚动位置做线性映射——这正是 scroll-timeline 的职责。
常见错误包括:
- 误以为加个
animation: fade-in 1s就能滚动触发 → 实际上没绑定时间线,动画只会播一次 - 把
scroll-timeline写在目标元素上 → 它必须写在**滚动容器**(如body或某个.section)上 - 用
scroll(root)却没设body高度或内容足够长 → 滚动范围不足,动画永远卡在 0% 或 100%
scroll-timeline 必须写在滚动容器上,且命名要合规
滚动容器得是实际发生滚动的元素。多数情况是 body,但现代写法更推荐用一个包裹层(避免 body 的兼容性陷阱):
.scroller {
height: 100vh;
overflow-y: scroll;
scroll-timeline: --text-fade y; /* 必须以 -- 开头,y 表示垂直滚动 */
}
注意点:
-
scroll-timeline的值格式是<name><axis></axis></name>,name必须是dashed-ident(即以--开头),不能写成text-fade或"text-fade" -
overflow-y: scroll或auto必须显式设置,否则滚动时间线无效 - 如果容器高度不够(比如内容只有一屏),滚动距离太短,动画会极速完成 → 可加
min-height: 200vh测试
动画关键帧要覆盖 0%→100%,且用 animation-fill-mode: forwards
文字渐显本质是 opacity 从 0 到 1,但必须确保动画播完后状态保留,否则会闪回透明:
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
<p>.text-item {
animation: fade-in linear;
animation-timeline: --text-fade;
animation-fill-mode: forwards; /<em> ⚠️ 必加!否则动画结束立刻 opacity=0 </em>/
}
</p>
容易忽略的细节:
- 没加
animation-fill-mode: forwards→ 文字闪一下就消失,像没生效 - 用
ease缓动会让淡入前半段太慢 → 苹果风格倾向linear或cubic-bezier(0.2, 0, 0.2, 1)(类似ease-out) - 若想让文字“从下往上浮出”,可叠加
transform: translateY(20px)到from,但注意只对合成属性(transform/opacity)才高性能
逐行错落出现?靠 animation-delay 或多个时间线
苹果官网常让同一组文字按顺序延迟淡入(第一行先显,第二行稍晚)。纯 CSS 方案有两种:
方案一:用 animation-delay 配合 :nth-child
.text-item:nth-child(1) { animation-delay: 0s; }
.text-item:nth-child(2) { animation-delay: 0.15s; }
.text-item:nth-child(3) { animation-delay: 0.3s; }
方案二:为每行定义独立滚动时间线(更精准,但略重):
.text-item:nth-child(1) { animation-timeline: --fade-1; }
.text-item:nth-child(2) { animation-timeline: --fade-2; }
/* 对应在 .scroller 上分别定义 --fade-1 y、--fade-2 y,并用 offset 控制起始位置 */
实际项目中,方案一更轻量;方案二适合需要严格对齐滚动位置的场景(比如某段文字必须在视口底部 20% 才开始淡入)。
真正难的是时间线范围控制和多元素节奏协调——它不像 JS 那样能随时读取 getBoundingClientRect(),所有偏移都得提前预设在 CSS 里。一旦设计变更,就得回头调 animation-delay 或时间线 start/end 偏移值。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











