欢迎来到我的公众号:前端侦探不得不说,CSS计数器是个好东西。最近有几篇文章用到CSS计数器,可以通过伪元素内容动态显示CSS变量,还可以制作很多有趣的动画。有兴趣的可以先回顾一下之前的文章:定时器还在用吗?CSS也可以实现电子钟动画合成小技巧!CSS实现动态倒计时效果自定义计数器提示!CSS实现长按类堆积动画的原理其实很简单。虽然content本身不直接支持CSS变量渲染,但是可以支持counter-resetcount::before{--percent:50;计数器重置:进度var(--percent);content:counter(progress);}通过一次传输,内容也可以支持CSS变量作为字符。这个技巧是从张新旭的文章中学来的,非常实用:Tips:如何使用content属性显示CSSvar变量值但是这个方法可惜的是CSS计数器不支持真正意义上的小数,即,如果CSS变量是小数,会直接显示为0count::before{--percent:50.15;counter-reset:progressvar(--percent);content:counter(progress);}那么,如何让content也支持CSS变量的小数显示呢,毕竟很多时候还是需要小数的呢?比如下面,如果支持小数,就可以轻松实现数字的滚动动画今天我们一起来探讨一下1.CSS原理拆解CSS计数器由于其特殊性,目前只支持整数。毕竟,自然数没有小数。(不排除以后可以实现自定义计数器)。这种情况下,我们可以换个思路,从数字形式上拆分出来。比如一个小数,48.69可以分解成48的整数部分和69的小数部分,再用小数点相连。这样拆分后都是整数,代码实现也支持css计数器(简单易懂,下面部分变量命名为中文,不建议实际生产)count::before{--integer:48;--十进制:69;counter-reset:整数计数器var(--integer)十进制计数器var(--decimal);内容:计数器(整数计数器)“。”计数器(十进制计数器);所以问题就变成了,如何拆分小数?2.将CSS变量拆分为整数和小数紧接着上面的问题,假设变量是--percent,问题是下面两个变量--integers和--decimals是如何通过--percent计算出来的?count::before{--percent:48.69;--整数:48;--十进制:69;counter-reset:整数计数器var(--integer)十进制计数器var(--decimal);内容:计数器(整数计数器)“。”counter(decimalcounter);}看起来很容易,但是用CSS实现起来好像不是很容易。要解决这个问题,您需要了解CSS自定义变量的类型。类型有很多种,下面列举一下custom-大部分ident可以看到具体类型。我们这里需要用到两种,和,它们都代表数字。具体区别是代表任意数字,整数和小数都可以用来代表整数,只有整数,小数会被认为是非法的回到这里,默认情况下,CSS变量可以是任意值,但是你可以指定它通过自定义变量@property变量的类型,可以转换无效的变量。@property-CSS(级联样式表)|MDN(mozilla.org)例如,如果我们需要一个整数,我们可以这样定义它,并将syntax属性设置为。@property--integer{语法:“<整数>”;/*整数*/初始值:0;inherits:false;}这样,这个变量就会被强制转换为整数。例如,下面的--integer也设置为小数count::before{--percent:48.69;--整数:48.69;--十进制:69;counter-reset:integervar(--integer)decimalvar(--decimal);内容:计数器(整数)“。”counter(decimal);}结果...居然直接变成了0?不过没关系,需要配合一些CSS计算函数来实现自动转换,比如calccount::before{--percent:48.69;--integer:calc(48.69);/*使用CSS计算后可以转换成整数*/--decimal:69;计数器重置:整数var(--integer)十进制var(--decimal);内容:计数器(整数)“。”counter(decimal);}然而,这里变成了49,原因其实是四舍五入,而不是四舍五入。为了消除这个误差,可以减去0.5,所以整数部分的最终实现是@property--integer{syntax:"";初始值:0;继承:false;}count::before{--percent:48.69;--integer:calc(var(--percent)-0.5);--十进制:69;计数器重置:整数var(--integer)十进制var(--decimal);内容:计数器(整数)“。”counter(decimal);}以后的css数学函数应该还有floor和ceil,可以期待一下~然后是小数部分,有了整数部分,小数部分就容易了,可以用整值相减整数部分,然后乘以100,如下代码实现所示为@property--decimal{syntax:"";初始值:0;继承:false;}count::before{--percent:48.69;--整数:calc(var(--percent)-0.5);--十进制:calc((var(--percent)-var(--integer))*100-0.5);计数器重置:整数var(--integer)十进制var(--decimal);内容:计数器(整数)“。”counter(decimal);}效果如下后面最后一个小数点因为四舍五入稍微有点偏差,没关系,可以改正,加0.01就可以了。其次,还有一个问题。当小数位小于10时,计算结果可能是这样的。在这种情况下,需要动态补零。“零填充”的技巧之前在这篇文章中有详细介绍:CSS也能自动补齐字符串吗?因此,只需要在计数器后面定义计数器样式decimal-leading-zero,也就是decimalleadingzero,最终实现如下count::before{--percent:48.69;--integer:calc(var(--percent)-0.5);--decimal:calc((var(--percent)-var(--integer))*100-0.5+0.01);计数器重置:整数var(--integer)十进制var(--decimal);内容:计数器(整数)“。”counter(decimal,decimal-leading-zero);}这样整数和小数都可以用同一个变量--percent表示,完美~3.CSS变量动画有些人可能会想,何必费那么大劲实现这样的功能?直接用js设置不行吗?如果只是数字上的变化,当然,但是在这里,除了CSS单变量带来的更好的可维护性之外,你还可以做一些即使在JS中也很难(或更昂贵)的事情,比如首先,让我们改进过渡动画。很多小数都是百分比的形式,也就是在0~1的范围内,所以前面的--percent可能是这样一个值0.4869count::before{--percent:0.4869;--percent:calc(var(--percent)*100);--integer:calc(var(--percent)-0.5);--decimal:calc((var(--percent)-var(--integer))*100-0.5+0.01);计数器重置:整数var(--integer)十进制var(--decimal);内容:计数器(整数)“。”counter(decimal,decimal-leading-zero)"%";}效果如下然后我们通过JS让数字随机变化count.addEventListener('click',ev=>{ev.target.style.setProperty("--百分比t",Math.random());})效果如下但是这样太死板了,我们需要一个数字变化时的动画,可以直接通过CSS自定义变量@property--percent{语法实现:"";initial-value:0;inherits:false;}count{/**/transition:--percent1s}现在看效果,很容易实现数字的滚动动画,因为小数部分跟随整数部分,比如整数从1变到3,那么小数部分会跟随两个循环的变化本来,这也是很有道理的,就像时钟的秒数永远比分数快,只是有些人可能会觉得变化太快了。有没有办法将小数部分和整数部分分开?当然,也是可以的,而且非常容易。您只需要分别为整数部分和小数部分设置转换。这两种效果大家可以自己选择,只是想象一下转场不一样。如果用JS实现这个效果,是不是还是有点麻烦?下面是完整的代码(不多,就几行)@property--percent{syntax:"";初始值:0;inherits:false;}@property--integer{syntax:"";初始值:0;继承:false;}@property--decimal{语法:“<整数>”;初始值:0;继承:false;}count{--percent:0.4512;字体大小:60px;字体粗细:更粗;游标:指针;font-family:'CourierNew',Courier,monospace;--percent:calc(var(--percent)*100);--integer:calc(var(--percent)-0.5);--decimal:calc((var(--percent)-var(--integer))*100-0.5+0.01);计数器重置:整数var(--integer)十进制var(--decimal);transition:--integer1s,--decimal1s;}count::before{content:counter(integer)"."counter(decimal,decimal-leading-zero)"%";}您也可以访问在线演示:CSSdoublenum(runjs.work)RunJS,前端代码在线创作与分享4.总结与解释以上就是全部内容了,很不错的小技巧,你学会了吗?CSS变量不支持直接在内容中渲染,但是可以借助计数器初始化来实现。CSS计数器不支持十进制初始化。支持小数的CSS计数器的实现原理是将小数拆分为整数、小数点和小数。CSS自定义变量可以指定变量的类型,从而可以通过CSS数学函数将小数转换为整数。小数部分可以通过减去整数部分得到。还需要通过小数前导零来完成位数。一方面,单个CSS变量可以带来更好的效果,另一方面,可以更轻松地实现过渡动画。使用@property可以很方便的控制CSS变量的transition和animation数字变化动画。在一些大屏显示数据的场景下还是比较实用的。有了CSS变量就不用再通过JS实时计算了。不过目前兼容性不是很好,适合内部项目小规模使用(当然直接用也没关系,唯一不支持的就是没有动画).最后,如果觉得对你有好处和帮助,欢迎点赞、收藏、转发???欢迎关注我的公众号:前端大侦探