我第一次做个人站的时候,几乎每个区块都有一个动效:标题打字、卡片倾斜、光标光斑、背景粒子、列表逐条 fade-in。
上线后自己看了三遍,感受是累。不是"信息太多"的累,是"页面一直在动"的累。
问题不在数量,在于「常驻」
把所有动效按触发方式分两类,问题立刻清楚:
| 类型 | 例子 | 特征 |
|---|---|---|
| 常驻 | 背景粒子、光标光斑、循环打字 | 你不动它,它也在动 |
| 触发式 | hover、滚动进入、点击展开 | 你不理它,它是静的 |
常驻动效的代价不在加载,而在注意力的持续占用。人是会一直看移动的东西的,这是生理反应,不是自律问题。
一屏里出现两个常驻动效,读者就无法专心读那一行字。
四条红线
于是我给自己的站点定了四条,写进规划文档当约束用:
第 3 条是最有用的。"承重"的意思是:删掉它,功能会缺损。 进度条承重,因为它告诉读者还剩多少;hover 反馈承重,因为它证明这行能点;背景极光不承重,所以它只能出现一次,在首屏。
落地之后长什么样
| 位置 | 效果 | 为什么留 |
|---|---|---|
| 首屏背景 | 极光着色器 | 全站唯一常驻动效,滚走即消失 |
| 标题 | 一个词循环解密 | 只对一个词,7 秒一次,不整句闪 |
| 列表入场 | 位移 8px / 220ms | 建立节奏,但小到几乎察觉不到"在动" |
| 行 hover | 纯 CSS 右移 2px | 0 成本,120ms |
| 效果页 | Dock / 滚动展开 / 波浪 | 默认静帧,想看的人自己点 |
| 工艺页尾 | 滚动背景序列 | 占三屏,只在 /craft,不进首页 |
位移只有 8px 这个数字是调出来的。试过 24px,节奏感更强,但读者会明确地"看到元素飞进来",注意力被动画本身吃掉了一半。
性能上的三个必做项
- WebGL 效果延后挂载:
requestIdleCallback之后才加载着色器模块,不抢首屏 JS。 - 减少动效偏好下不加载:
prefers-reduced-motion时直接给静态渐变,不是把速度调成 0.01。 - 只动
transform与opacity:这两个属性不进布局,也不重绘。
// 降级的判据只有一个,组件不许自己判断
const reduced = usePrefersReducedMotion()
if (reduced) return <StaticGradient />反过来想
一个更简单的判据:如果把这个动效换成一张静帧,页面会损失什么?
如果答不出来,它就不该存在。这个标准很残酷,但它能过滤掉九成"看起来很酷"的想法——而剩下的那一成,才是审美。
按这条预算做出来的一个完整例子是 滚动背景序列:它必须占三屏、只能出现在一个位置,做的时候还得为它单独算一遍合成亮度。
留言
还没有人说话读到这里,说两句。不用登录,昵称随便填。