偶尔在网上看到这样的设计。当阅读量比较小的时候,文字是灰色的。当阅读量比较大(>=100)时,文字变成棕色。示意图效果如下:是不是很醒目?另外还有一个可以根据进度自动变色的进度条,如下:其实这样的逻辑判断也可以通过纯CSS实现,主要是利用CSS变量和边界值计算。下面分享一下:1.基本数学原理CSS中没有直接的if判断逻辑。要达到这样的效果,就需要充分利用CSScalc的计算特性和临界条件。假设要实现这样一个逻辑:--x的默认值为10,当变量--y大于等于100时,--x变为20,如何实现呢?这里先给出答案,再分析:--x:clamp(10,(var(--y)-99)*99,20)这里用到了clamp函数,可以理解为区间,有3个值[Min,Val,Max],前面和后面分别是最小值和最大值,中间是动态值。这其实是一个简单的线性函数,而且是单调递增的,所以这里的逻辑是:当--y小于100的时候,比如99,(var(--y)-99)*99的计算结果为0,再小则为负数。取区间[10,20]中较小的值,所以最终结果为10。当--y大于等于100时,如100,(var(--y)-99)的计算结果*99就是99,在区间[10,20]中取较大的值,所以最后的结果是20。用一张图表达如下:这里为什么要乘以99?它实际上是一个放大的插值操作。严格来说,本例中只要大于20就可以了。乘以20后,范围变成...,-20,0,20,40,...也包括区间[10,20]。这就是CSS中if判断的基本原理。使用了一点数学运算。接下来我们来看看实战效果。2.首先通过饱和度的变化做一个简单的布局;由于纯CSS无法获取值的大小,需要使用CSS变量进行计算,所以HTML可以这样。1阅读99阅读102reading如果不考虑HTML语义或SEO等因素,这里的“numbers”和“reading”可以传递通过伪元素来生成;num::before{计数器重置:numvar(--num);content:counter(num);}num::after{content:'reading';}因此,HTML可以进一步简化为:简单修改后的效果如下:由于是灰色和棕色之前的变化,简单的方法就是控制它通过饱和。比如这里棕色的颜色是#aa540e,用hsl颜色表示为hsl(27,50%,36%),如下:这里的Saturation控制颜色的鲜艳程度。饱和度越高,颜色越亮,饱和度越低,颜色越暗。当饱和度降到0时,就完全变成灰色了,如下:所以,这里要在两种颜色之间切换,可以计算饱和度,具体规则是。当--num大于等于100时,饱和度为85%,否则为0%,利用上一节的基本原理,所以实现。num{--s:clamp(0%,(var(--num)-99)*99%,85%);/*>100*/颜色:hsl(27var(--s)36%);}逻辑同上,这里不再赘述。实际效果如下:Kapture2022-04-21at15.55.20由于饱和度本身也有一个“阈值”,当饱和度低于0%时,仍然渲染为0%,所以上面的实现可以去掉最小值,简化如下:num{--s:min((var(--num)-99)*99%,85%);color:hsl(27var(--s)36%);}也可以达到同样的目的。3、完整的色彩控制虽然饱和度的变化控制比较容易,只需要控制一个参数,但还是有一定的局限性。首先,这个灰色可能不是设计师想要的灰色(实际上可能会稍微浅一点)。而且,换色不够自由。比如默认是蓝色,一定量后变成红色。控制住。因此,我们需要以完全解析的方式来实现它。原理是控制颜色的三个参数,要么rgb,要么hsl,假设两种颜色分别为rgb(29125250)和rgb(2446754),如下:不仅有递增的变化,还有递减的变化(例如125=>67,250=>54),所以计算calc时需要取反。具体实现如下:num{--r:clamp(29,(var(--num)-99)*999+29,250);/*29,250*/--g:clamp(67,(var(--num)-100)*-999+67,125);/*128,67*/--b:clamp(54,(var(--num)-100)*-999+54,250);/*250,54*/color:rgb(var(--r)var(--g)var(--b));}注意点:系数要足够大,这里是999,比如第一项,当--num为100时,如果系数为99,那么计算结果为99+29,没有达到最大值250,所以需要改大一点的值,比如999。clamp支持的参数必须是[min,val,max],并且min和max不能调换,所以上面的代码在实现的时候调换了。实际效果如下:Kapture2022-04-21at16.43.244.自动改变背景颜色虽然通过上述方法可以自动改变颜色,但还是有些不雅。代码量比较大,有些繁琐,容易混淆,尤其是前后数字的顺序。仅适用于两种颜色的变化,例如多段颜色,可能是不可能的。与纯色相比,背景在多层叠加上有非常大的优势。如果你控制了每个背景的大小,你能控制最终显示的颜色吗?还是上面的例子,我们先通过渐变绘制两层背景,最上面是红色rgb(2446754),最下面是蓝色rgb(29125250),然后通过background控制每一层的大小-尺寸。原理是这样的:具体实现如下:num{background:linear-gradient(rgb(2446754),rgb(2446754)),linear-gradient(rgb(29125250),rgb(29125250));颜色:#fff;background-size:calc((var(--num)-99)*100%),100%;}其实这个计算很简单,解释一下:当--num大于等于100时,计算结果必须大于100%,所以上面的红色背景是可见的,整体呈现红色。当--num小于100时,计算结果必须小于等于0%。即使是负数,background-size解析为0%,所以上面的红色背景是看不见的,下面整体表现为蓝色。实际表现如下:Kapture2022-04-21at18.19.56如果想改变文字颜色,可以使用background-clip。num{背景:线性渐变(rgb(2446754),rgb(2446754)),线性渐变(rgb(29125250),rgb(29125250));颜色:透明;背景大小:calc((var(--num)-99)*100%),100%;-webkit-background-clip:text;}Kapture2022-04-21at18.29.38比上面的方法简单多了么?5.自动变色进度条背景也可以适配多种颜色。接下来我们看文章开头的一个案例,实现这样一个可以自动变色的进度条。有几个规则:当进度低于30%时,背景为红色。当进度大于30%且小于60%时,背景为橙色。当进度大于60%小于90%时,背景为蓝色。当进度大于90%时,背景为绿色。原理图如下:假设HTML如下:
CSS变量可以通过CSS伪类和计数器显示在页面上.有兴趣的可以看看张新旭老师的这篇文章:小技巧:如何使用content属性显示CSSvar变量值[1](本例也是在此基础上修改的),简单修改它。.bar{显示:flex;高度:20px;背景色:#f5f5f5;}.bar::before{counter-reset:progressvar(--percent);内容:计数器(进度)'%\2002';显示:弹性;证明内容:结束;宽度:计算(变量(--百分比)*1%);字体大小:12px;颜色:#fff;背景:#2486ff;white-space:nowrap;}效果如下:那么如何根据进度自动改变颜色呢?原理是一样的!首先通过渐变绘制几种颜色,最后的颜色放在最前面,然后根据CSS变量控制背景大小。原理如下:因为background-size本身是有边界限制的。当小于0%时,仍然会渲染成0%,所以不需要用clamp来限制,减少代码量。具体代码实现是这样的:.bar::before{/*Othersstyle*/background-image:linear-gradient(green,green),linear-gradient(#2486ff,#2486ff),linear-gradient(orange,橙色),线性渐变(红色,红色);背景大小:calc((var(--percent)-90)*100%)100%,calc((var(--percent)-60)*100%)100%,calc((var(--percent)-30)*100%)100%,100%100%;}简单看一下里面的逻辑:当--percent大于90时,所有背景的尺寸为100%,最上面的绿色为自然展现。当--percent大于60小于等于90时,只有顶层的绿色尺寸为0,其他背景尺寸为100%,所以显示第二层的蓝色。--percent大于30小于等于60时,上两层背景尺寸为0,下两层背景尺寸为100%,所以显示第三层橙色.当--percent小于30时,只有底层大小为100%,其他为0,所以底层显示为红色。实际表现如下:Kapture2022-04-21at23.00.00已经实现了背景颜色的自动变化,但是数字还是有点小问题。当进度条比较小时,百分比数字明显放不下,如下:所以,这种情况下Down应该把百分比数字移到外面,变成红色。向外移动可以通过text-indent属性实现。文字颜色由白变红(hsl(0,100%,50%)),可以通过亮度来实现。当亮度为100%时,任何颜色都会变成白色,由于亮度本身的限制,当超过100%时,仍然会以100%渲染,可以使用。具体实现如下:.bar::before{/*otherstyles*/--l:max(50%,(var(--percent)-9)*100%);颜色:hsl(0,100%,var(--l));--offset:clamp(0%,(var(--percent)-10)*-120%,120%);text-indent:var(--offset);}这里的计算原理也和前面一样,大家可以在这里仔细斟酌。实际效果如下:Kapture2022-04-21at23.46.59可以看到当百分比小于10时,文字在外面,避免了空间不足的情况,非常聪明。完整的代码可以访问:CSSautocolor(codepen.io)[2]或CSSautocolor(juejin.io)[3]。6.总结以上就是关于CSS自动换色技术的全部内容。核心其实就是边界值的灵活计算。是不是很厉害?这里总结一下实现要点:实现原理是CSS变量和calc计算;clamp可以限制expression公式的区间范围;通用核心代码--x:clamp(10,(var(--y)-99)*99,20);饱和度可以控制颜色的鲜艳程度,当饱和度为0时,就变成灰色;完全控制颜色变化,可以完全用rgb或hsl表示,单独计算;以上方案只适用于两种颜色的切换;多层背景叠加可实现多色切换;多层背景切换的核心是控制背景的大小;当亮度为100%时,颜色变为白色;有些属性本身就有“阈值”,充分利用这个特性可以减少区域判断。当然,这个技巧不仅仅适用于颜色的变化,只要是值的变化,比如文章中的文本缩进切换,充分利用这些小技巧,可以让我们的页面更??加灵活精致。