content属性不可动画,真滚动需用transform位移预排数字;必须用等宽字体+tabular-nums、严格容器高度、正确calc计算和专用cubic-bezier缓动。

为什么直接用 content + @keyframes 做不了真滚动
很多人一上来就写 @keyframes 试图让 ::after 的 content 从 "0" 变到 "9",结果发现根本不会动。因为 content 属性本身不可动画,CSS 动画无法对字符串值做插值——它不是数值,没有中间态。浏览器看到 from { content: "3"; } 和 to { content: "7"; },只会硬切,不触发任何过渡。
真正能动的,是位置、颜色、缩放这类可插值属性。所以所有靠谱的 CSS 数字滚动方案,本质都是「位移预排数字」:把 0–9 垂直堆成一列,靠 transform: translateY() 把对应数字“拉”进视野区。
transform: translateY(calc(var(--digit) * -100%)) 这行代码里每个符号都不能错
这行样式是整个滚动效果的锚点,但极易因单位、符号或计算顺序出错:
-
-100%必须带负号:正号会让数字往下滚出视野,直接看不见 -
calc(var(--digit) * -100%)不能写成calc(-100% * var(--digit)):旧版 Safari(iOS 15.4 之前)解析失败 - 容器
height必须严格等于单个数字高度:如果设height: 48px但line-height: 46px,100%就不是 48px,位移失准 - 禁用
em/rem设容器高:父级font-size一变,整个滚动节奏就乱
等宽字体不是“建议”,是运行前提
“1”比“0”窄、“7”比“8”细——这是绝大多数字体的默认行为。一旦堆叠后位移,上下数字边缘立刻错位,看着就像抖动或歪斜。
立即学习“前端免费学习笔记(深入)”;
必须同时满足三项:
- 显式声明字体链:
font-family: 'SF Mono', 'Consolas', 'Roboto Mono', monospace - 强制启用等宽数字:
font-variant-numeric: tabular-nums(在 DevTools 的 Computed 面板确认生效) - 用 ruler 工具量
0123456789每个字符像素宽度,确保完全一致(例如全是 24px)
纯 monospace 不保证数字等宽;iOS Safari 15.4 之前不支持 tabular-nums;没验证生效就上线,90% 概率翻车。
缓动曲线 cubic-bezier(0.33, 1, 0.68, 1) 别手滑改
数字切换是离散跳变(3 → 4),不是连续插值。默认 ease 在起止点加速度突变,人眼明显感知“顿一下”。
这个贝塞尔曲线是专为数字滚动调优的:
- 起始缓入:避免生硬弹出
- 中间接近线性:保证滚动过程稳定匀速
- 结束强缓出:模拟滚轮惯性停稳,视觉更自然
换成 ease-in-out 或随便调参数,大概率出现卡顿、跳帧或收不住的晃动感。它不是风格选项,是功能依赖。
多位数字联动时,小数位移会累积发虚;JS 频繁更新 --digit 而上一次 transition 没结束,就会跳变——这些细节不提前压住,上线后用户第一眼看到的就是错位和卡顿。


















