纯 CSS 动效

不引动画库:弹簧缓动、页面过渡、滚动驱动、首帧入场、高度到 auto。每块右上角显示你的浏览器支不支持;系统开了「减少动态效果」时全部关掉。

01弹簧缓动 linear()

把阻尼弹簧采样成 31 个点写进 linear():冲过头一点再回来。红线 = --spring(过冲约 16%),蓝线 = --spring-soft(约 8%),灰线是普通的 ease-out。

1.0 0 时间
ease-out
--spring
--spring-soft

02页面过渡 View Transitions

点一篇:旧画面上移淡出、新画面弹着落下,被点的标题直接「飞」成下一页的大标题。

03滚动驱动 animation-timeline

在框里滚动:顶上红条是阅读进度(scroll()),卡片进入视口时浮上来(view())。全程没有一行 JS。

  1. 01进度条跟着滚动条走,不监听 scroll 事件。
  2. 02卡片从下方 36px 浮上来,同时淡入。
  3. 03animation-range: entry 0% entry 75% 决定什么时候播完。
  4. 04动画跑在合成线程,滚得再快也不掉帧。
  5. 05不支持的浏览器直接显示静止的内容。
  6. 06减少动态效果时整段关掉。
  7. 07再往下一点。
  8. 08到底了,进度条也满了。

04首帧入场 @starting-style

新插入的元素第一次渲染时从 @starting-style 里的样子过渡过来,不用写 keyframes,也不用等一帧再加类。

01已保存草稿
02复制好了

05高度到 auto interpolate-size

以前 height: 0 → auto 不能过渡,只能量高度写死。现在根上一句 interpolate-size: allow-keywords 就行,还能配弹簧。

展开的高度是内容自己撑出来的,换文字、换字号都不用改 CSS。

不支持的浏览器会直接跳到展开状态,没有动画但不坏。

06按下回弹 · 悬停抬起

按钮按下 scale: .93,松手用弹簧弹回;卡片悬停抬起 3px、轻轻歪一点。都是一行 transition。

把鼠标放上来translateY(-3px) rotate(-.4deg)