FLIP 布局动画
FLIP
FLIP Flip 动画 布局过渡 Layout Animation First Last Invert Play 共享元素过渡
GSAP 动画先记录元素当前位置,直接修改 DOM 布局,再从旧状态平滑过渡到新状态;GSAP 的 Flip 插件把这套流程封装成两步调用。
又称:Flip 动画 · 布局过渡 · Layout Animation · First Last Invert Play · 共享元素过渡
- GSAP
- CSS
- Claude / Cursor
1
2
3
4
5
6
Prompt 片段
用 GSAP Flip 实现网格与列表视图切换:点击按钮前 Flip.getState(items),切换容器的 is-list 类,再 Flip.from(state, { duration: 0.9, ease: 'expo.inOut', stagger: 0.03, absolute: true })。筛选商品卡片时用 Flip 做过渡:保留下来的卡片平滑移动到新位置,新出现的用 onEnter 淡入,被筛掉的用 onLeave 淡出。点击缩略图时把它移动到详情容器里(appendChild),用 Flip 让图片从缩略图位置放大到详情位置,开启 scale: true 以提升性能。
是什么
FLIP 是 First、Last、Invert、Play 四个词的缩写,是一种布局动画技巧:先记录元素的初始位置(First),直接把 DOM 改成最终布局(Last),计算两者差值并用 transform 把元素「拉回」原处(Invert),最后移除这个偏移并播放动画(Play)。这样就能在不逐帧改变布局的前提下,让任何布局变化都平滑过渡。
GSAP 的 Flip 插件随 gsap 包免费提供,从 gsap/Flip 导入。它把这套流程简化为:Flip.getState() 记录状态,你随意修改 DOM,然后 Flip.from(state) 播放过渡。上方演示中,6 个色块在三列网格和单列列表之间切换,同时打乱顺序,每个色块都从原位置平滑移动并缩放到新位置。
核心参数
| 参数 | 含义 |
|---|---|
duration / ease |
过渡的时长与缓动 |
absolute |
过渡期间把元素设为绝对定位,避免 Grid、Flex 布局互相挤压 |
stagger |
让元素依次开始归位 |
nested |
嵌套元素同时变化时,避免位移被重复计算 |
scale |
用 scaleX/scaleY 代替 width/height 过渡,性能更好 |
onEnter / onLeave |
处理新出现和被移除的元素 |
代码示例
import { gsap } from 'gsap';
import { Flip } from 'gsap/Flip';
gsap.registerPlugin(Flip);
const grid = document.querySelector('.grid');
const items = gsap.utils.toArray('.item');
document.querySelector('.toggle').addEventListener('click', () => {
const state = Flip.getState(items); // 1. 记录当前位置与尺寸
grid.classList.toggle('is-list'); // 2. 直接修改布局
gsap.utils.shuffle([...items]).forEach((el) => grid.appendChild(el));
Flip.from(state, { // 3. 从旧状态过渡到新状态
duration: 0.9,
ease: 'expo.inOut',
stagger: 0.03,
absolute: true,
});
});
什么时候用
- 网格与列表视图切换、卡片排序和筛选。
- 缩略图展开为详情、元素在不同容器间移动。
- 任何「布局由 CSS 决定、只想让变化过程更顺滑」的场景。
常见误区
- 在修改 DOM 之后才调用
Flip.getState():记录到的已经是最终状态,动画不会发生。 - 在 Grid 或 Flex 容器中不开
absolute:过渡期间元素仍参与布局,会出现跳动。 - 用它做纯装饰性的位移:如果起止位置都是已知数值,直接写补间更简单。