数字滚动本质是通过transform: translatey()位移切换预排数字,非3d动画;需等宽字体、overflow: hidden、css自定义属性配合calc()与cubic-bezier过渡实现平滑效果。

数字滚动效果的本质是位移切换,不是动画插值
数字滚动效果看着像“数字在滚轮里翻转”,实际几乎全是用 transform: translateY() 把一串预排好的数字上下位移实现的。浏览器不渲染真实 3D 翻转,因为成本高、兼容性差、字体对齐难。你看到的“滚动”,其实是把 0 到 9 垂直堆成一列,再通过改变容器的 transform 值,让对应数字“滑”到可视区中心。
- 必须用固定等宽字体(如
font-family: monospace或'SF Mono', 'Consolas'),否则数字上下错位 - 每个数字高度要严格一致,推荐用
line-height: 1+height显式设为单行高 - 容器需设
overflow: hidden,否则滚动时看到多余数字溢出
用 CSS 自定义属性 + transition 实现平滑滚动
核心思路:用一个 --digit 自定义属性控制当前显示数字,CSS 用 calc() 算出对应位移值,配合 transition 实现缓动。不依赖 JS 动画帧,更轻量、更易同步多个数字。
-
--digit值应为 0–9 的整数,JS 只需更新这个属性:el.style.setProperty('--digit', 7) - 位移公式固定为:
transform: translateY(calc(var(--digit) * -100%)),前提是每个数字占容器 100% 高度 - 必须加
transition: transform 0.3s cubic-bezier(0.33, 1, 0.68, 1),默认ease在数字切换时有明显“顿挫” - IE 不支持
calc()里用自定义属性,如需兼容 IE,得退回到 JS 控制style.transform
多个数字联动时,避免小数位移导致的模糊
当同时滚动年份(4 位)、时间(6 位)这类多位数字时,如果每位都独立用 % 单位位移,小数像素会累积,导致文字发虚或闪烁。
- 强制启用硬件加速:
transform: translateZ(0)或will-change: transform(仅对频繁变化的元素) - 所有数字容器统一用
font-size整数值(如24px,不用1.5rem),避免缩放引入小数 - 位移值改用
px更稳妥:若单个数字高32px,则写transform: translateY(calc(var(--digit) * -32px)) - Chrome 115+ 对 subpixel rendering 优化变严,若仍模糊,可加
-webkit-font-smoothing: antialiased
JS 更新数字时,注意异步时机与过渡中断
直接连续多次设置 --digit,可能因上一次 transition 没结束就被覆盖,导致跳变或卡住。
- 用
getComputedStyle(el).getPropertyValue('transform')判断是否还在过渡中(不推荐,性能差) - 更可靠的是加个简单防抖:每次更新前
clearTimeout(timer),再timer = setTimeout(() => el.style.setProperty(...), 16) - 若需精确控制滚动节奏(比如倒计时每秒跳一次),直接用
el.style.transition = 'none'瞬间跳到目标值,再恢复transition - 别在
requestAnimationFrame里反复 setProperty——它比 CSS transition 还慢,反而拖累帧率
CSS 数字滚动真正难的不是位移本身,而是字体渲染一致性、小数像素控制、以及 JS 更新节奏和 CSS 过渡的咬合。这些地方一松,滚动就糊、就跳、就不同步。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











