数字滚动
Count Up
数字从 0 快速滚到目标值,然后停住。
- 又叫:
- 数字递增
- 数值动画
- 计数动画
- count up
- number counter
- animated counter
- 展厅
- 排版与文字
- 形态
- 固定舞台
- 播放
- 重播
- 关键词
- 需要 JS / 浏览器 API / 字体特性 / 主线程每帧 / 可以直接用
参数工作台
复制给 AI
随参数实时更新做一个数字滚动(count up):数字在 1200ms 内用 easeOutExpo 缓动从 0 滚到 12800,每三位加千分位,用 requestAnimationFrame 按时间戳算进度,不要用 setInterval。容器用 font-variant-numeric: tabular-nums 并预留宽度,避免位数变化时抖动;系统开启减少动态效果时直接显示 12800。
count up animation, animate number from 0 to 12800 in 1200ms with easeOutExpo easing, requestAnimationFrame with timestamp-based progress, font-variant-numeric: tabular-nums, thousands separator, reserve width to avoid layout shift, respect prefers-reduced-motion (render final value)
https://publieople.github.io/design-museum/entry/count-up/?stage=light
链接带着你调好的参数
什么时候用
- 数据面板的关键指标第一次出现,想让数字有涨上去的感觉
- 首屏用一两个大数字当主角,给一个短促的入场
- 想让数字滚动在进入视口后再开始,而不是页面一打开就已经跳完
适用场景:页面 / 卡片 / 列表
推荐取值
- 时长
- 800–1500ms
- 缓动
- easeOutExpo / easeOutCubic
- 数字排版
- font-variant-numeric: tabular-nums
- 触发
- IntersectionObserver,threshold 0.3
- 终值停留
- 滚完至少 300ms 不再变化
别搞混
和「机械翻牌 odometer」的区别
odometer 是每一位数字上下滚动或翻页,位与位之间有物理位移;数字滚动只是数值在变,字形本身不动。
和「CSS @property 数值动画」的区别
@property 可以注册一个整数自定义属性再交给 counter() 渲染,纯 CSS 就能跑,但插值交给浏览器,格式和缓动不好控;要精确控制格式、缓动和重播,用 requestAnimationFrame 手写更稳。
容易踩的坑
- 位数变化会撑动布局(9 变 10、99 变 100),给容器预留宽度,并用 font-variant-numeric: tabular-nums 让每位数字等宽。
- requestAnimationFrame 循环要在组件卸载时 cancel,否则组件没了还在 setState。
- rAF 回调拿到的是高精度时间戳,用它减去开始时间;不要和 Date.now() 混算,也不要拿 setInterval 每帧加固定值,掉帧时会越走越慢。
- 服务端渲染和首次客户端渲染必须渲染同一个值(通常是 0),否则 hydration 对不上;挂载之后再开始跑。
- prefers-reduced-motion 下直接显示最终值,别让数字再滚一遍。
无障碍降级
prefers-reduced-motion: reduce 时不跑帧循环,直接把目标值一次性渲染出来。
关键词
- requestAnimationFrame
- tabular-nums
- font-variant-numeric
- easeOutExpo
- count up animation
- IntersectionObserver