页面过渡不是为了炫技,而是为了让用户理解“我从哪里来,又到了哪里去”。在个人博客里,动效可以更轻一点:进入时有层次,离开时不打扰阅读,滚动时给一点反馈。
基本思路
我会把动效拆成三类:首屏进入、列表 stagger、滚动进度。首屏进入负责建立情绪,列表 stagger 让信息更容易扫描,滚动进度则给长页面一个方向感。它们不应该互相争抢注意力,而是像页面自己的呼吸。
实际设计时,我先把页面拆成几个稳定层级:导航、主标题、正文卡片、侧边信息。动画只作用在层级切换上,不直接改变内容结构。这样后续即使调整布局,动效依然可以复用。
在 Nuxt 中落地
Nuxt 的页面结构天然适合做局部动效。页面只需要给关键模块加上稳定的选择器,然后在客户端用 GSAP 处理进入节奏。这样不会污染内容层,也不会把样式写成难以维护的状态机。
我的习惯是让组件只声明“这里可以被动画处理”,真正的时间线放在 composable 里。比如卡片统一使用 data-animate 标记,页面挂载后再收集这些节点。这样不同页面可以共用同一套 reveal 逻辑,也能统一处理销毁。
const scope = gsap.context(() => {
gsap.from('[data-animate]', {
y: 18,
opacity: 0,
duration: 0.64,
ease: 'power3.out',
stagger: 0.08
})
}, root)
这段代码的重点不是参数,而是边界:动画只读取 root 内的节点,并在页面卸载时统一 revert。否则切换路由几次后,页面状态会变得很难追踪。
页面切换的节奏
页面切换可以分成两个阶段:旧页面离开,新页面进入。个人博客不需要复杂的转场遮罩,最稳定的做法是让旧页面轻微淡出,新页面带一点位移进入。切换应该快,不能让用户觉得等待是动效的一部分。
如果页面内容来自异步数据,动画要等关键内容准备好再启动。否则用户会看到空卡片先动,文字后出现,这种错位会让动效显得廉价。
控制克制
好的动效应该能被感觉到,但不应该抢走内容注意力。我的默认规则是:位移短、时间短、缓动柔和,并尊重系统的减少动态效果设置。
我会给自己设几条限制:
- 单个 reveal 动画尽量控制在 700ms 内。
- 列表 stagger 不超过 100ms,否则大列表会拖慢阅读。
- 不给正文段落逐段加动画,正文是阅读对象,不是舞台。
- 系统开启减少动态效果时,所有装饰动画都应该停止。
最后
GSAP 很强,但页面动效真正难的不是 API,而是判断“哪里不该动”。个人博客的气质应该来自内容和排版,动效只是帮助页面更自然地出现。
