你以为页面丝滑只能靠 GSAP?配了八年动画,今天三行 CSS 把这件事彻底原生化了
写过前端的都踩过这个坑——页面过渡要丝滑、滚动动画要进场、视差效果要流畅,第一反应就是装 GSAP 或者 Framer Motion。30KB~50KB 的 JS 库往 bundle 里一塞,动画确实跑起来了,但 LCP 多了 60ms,INP 多了 70ms,主线程还时不时抖一下。到了 2026 年,这件事被两套浏览器原生 API 从根上翻了过来。
View Transitions API 和 CSS Scroll-Driven Animations 在 2026 年的覆盖情况是这样的:同文档 View Transitions( SPA 内的状态过渡)Chrome 111+/Safari 18+/Firefox 144+ 全部支持,Baseline 2026 约 89%;跨文档 View Transitions(多页站点的页间过渡)Chrome 126+/Safari 18.2+ 支持,Firefox 144+ 部分支持;Scroll-Driven Animations(滚动绑定动画)Chrome 115+/Safari 18+/Firefox 132+ 支持。三大引擎全部稳定,覆盖率约 95%,比很多业务项目的最低兼容版本还高。
先说 View Transitions。SPA 里用 document.startViewTransition() 把 DOM 变化包起来,浏览器自动在旧状态和新状态之间做交叉淡入淡出。多页站点的跨文档过渡更简单——全局 CSS 加一句 @view-transition { navigation: auto; },从此每次页面跳转都自带过渡动画,连 Framer Motion 都不用装。如果你想让列表卡片的某个区块”飞”到详情页的对应位置,给它加一个 view-transition-name,浏览器自己算两张快照之间的形变路径,Framer Motion 的 Shared Element 动画两行 HTML 属性就替代了。
/* 跨文档过渡,最基础的配置 */
@view-transition { navigation: auto; }
/* 给特定元素命名,浏览器自动计算形变路径 */
.hero-image { view-transition-name: hero; }
再说 Scroll-Driven Animations。以前写一个”元素滚入视口时淡入”,要写 IntersectionObserver、addClass、requestAnimationFrame 一整套 JS,现在三行 CSS:
.reveal {
animation: fade-up linear both;
animation-timeline: view();
animation-range: entry 0% entry 30%;
}
@keyframes fade-up {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
animation-timeline: view() 把动画进度绑定到元素进入视口的过程,animation-range 控制在哪一段播放。阅读进度条更简单,把 scroll() 当 timeline 传进去,整个页面从顶滚到底,进度条自动从 0% 到 100%,零 JS。
这两个 API 有一个共同的核心优势:运行在合成线程,不占主线程。Mintec 和 Frontend Horizon 两家技术团队在 2026 年的生产环境实测数据高度一致:把 Framer Motion 迁移到原生方案后,JS bundle 减少 27%~38KB,p75 INP 从 268ms 降到 152ms(改善 43%),LCP 提升 280ms~320ms,移动端 Lighthouse 性能分从 72 提到 89。动画库 46KB 加进去带来的 INP 惩罚是 50ms~70ms,CSS 原生方案是 0ms——在 INP 已经纳入 Google 排名信号的 2026 年,这个差距是真实业务影响,不是数字游戏。
什么时候还是要用动画库?手势类动画(拖拽、滑动卡片)CSS 做不到;弹簧物理动画(spring、momentum)CSS easing 模拟不了;复杂编排序列(多元素协调时序)CSS keyframes 写到后面没法维护。这三个场景下 Motion One 或 @react-spring/web 是合理选择——但为了一个淡入效果装 Framer Motion,在 2026 年真的可以重新评估一下了。
实操路径:先在全局 CSS 加上 @view-transition { navigation: auto; } 配 prefers-reduced-motion 包裹,用 @supports (animation-timeline: view()) 把 Scroll-Driven Animations 包起来做渐进增强,跑一遍 Lighthouse 对比 INP/LCP 数据,心里有数之后再决定哪些场景真的需要动画库。这样一步一步来,不是一次性全撤,风险可控。
迁移收益很实在:bundle 小了,动画不占主线程了,INP 变好看了,视觉体验没打折扣。浏览器平台兜底,不用自己维护一套 JS 动画基础设施。
评论区
登录后可评论。