乐趣区

关于前端:CSS-变量自动变色技术

欢送关注微信公众号:前端侦探

在思否上看到这样一个设计,当浏览量比拟少时,文字呈灰色,当浏览量比拟多(>=100)时,文字就变成褐色了,示意成果如下

是不是十分醒目呢?

另外,还有那种能够依据进度主动变色的进度条,如下

其实通过纯 CSS 也能实现这样的逻辑判断,次要用到了 CSS 变量和边界值计算,当初分享一下

一、根本数学原理

CSS 中并没有间接的 if 判断逻辑。要实现这样一种成果,必须充分利用 CSS calc 的计算个性和临界条件。

假如要实现这样一个逻辑:

--x默认值为 10,当变量 --y 大于等于 100 时,--x变为 20

如何实现呢?这里先给出答案,而后进行剖析

--x: clamp(10,(var(--y) - 99) * 99,20)

这里用到了 clamp函数,你能够了解为一个区间,有 3 个值 [Min, Val, Max],前后别离是最小、最大值,两头是动静值,这里其实就是一个简略的线性函数,并且枯燥递增,所以这里的逻辑就是:

  1. --y 小于 100 时,比方 99,(var(--y) - 99) * 99 的计算结果是 0,再小就是正数了,在 [10, 20] 区间中取较小值,所以最终后果是 10
  2. --y 大于等于 100 时,比方 100,(var(--y) - 99) * 99 的计算结果是 99,在 [10, 20] 区间中取较大值,所以最终后果是 20

用一张图示意如下

为什么这里须要乘以 99 呢?其实是一个 放大插值 的操作,严格来讲,这个例子中只有大于 20 就够了,当乘以 20 当前,范畴就变成了 ...、-20、0、20、40、...,也是蕴含 [10, 20] 这个区间的。

这个就是 CSS 中 if 判断的基本原理了,用到了一点点数学运算,接下来看实战成果

二、通过饱和度变动

首先简略布局一下

因为纯 CSS 无奈获取到数值的大小,这里须要借助 CSS 变量进行计算,所以 HTML 能够这样

<num style="--num:1">1<span> 浏览 </span></num>
<num style="--num:99">99<span> 浏览 </span></num>
<num style="--num:102">102<span> 浏览 </span></num>

如果 不思考 HTML 语义或者 SEO 这类因素,这里的“数字”和“浏览”都能够通过伪元素来生成

num::before {counter-reset: num var(--num);
  content: counter(num);
}
num::after {content: '浏览';}

于是,HTML 能够进一步简化为

<num style="--num:1"></num>
<num style="--num:99"></num>
<num style="--num:102"></num>

简略润饰后成果如下

因为是灰色和褐色之前的变动,一种简略的形式是通过饱和度来管制,比方这里褐色的色彩是#aa540e,用 hsl 色彩示意就是 hsl(27, 50%, 36%),如下

这里 饱和度能够管制色彩的娇艳水平 。饱和度越高,色彩越娇艳,饱和度越低,色彩越黯淡, 当饱和度降为 0,就变成彻底的灰色 了,如下

所以,这里要实现两种色彩的切换,能够通过计算饱和度,具体规定就是

--num大于等于 100 时,饱和度为 85%,否则为 0%,利用后面一节的基本原理,所以实现就是

num{--s: clamp(0%,(var(--num) - 99) * 99%,85%);/* >100 */
  color: hsl(27 var(--s) 36%);
}

逻辑和后面统一,这就不反复了,实际效果如下

因为饱和度自身也有“阈值”,当饱和度低于 0% 时,依然依照 0% 来渲染,所以下面实现能够去除最小值,简化后如下

num{--s: min((var(--num) - 99) * 99% ,85%);
  color: hsl(27 var(--s) 36%);
}

同样能达到雷同的目标

三、齐全色彩管制

尽管饱和度变动管制比拟容易,只须要管制一个参数就行了,但还是有些局限性。首先,这个灰色可能并不是设计师想要的灰色(理论可能会偏淡一点),再者,色彩变动不够自在,比方,默认是一个蓝色,超出肯定数量后变成红色,这种就无法控制了。

于是,咱们须要用齐全解析的形式来实现,原理其实就对色彩的 3 个参数进行管制,rgb 或者 hsl 都能够,假如两个色彩别离是 rgb(29 125 250)rgb(244 67 54),如下

这里不仅有 递增 的变动,也有 递加 的变动(比方,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));
}

须要留神几点:

  1. 系数须要足够大,这里是 999,比方第一条,当 –num 为 100 时,如果系数是 99,那么计算的后果是 99 + 29,没有达到最大值 250,所以须要改大一点,比方 999
  2. clamp 反对的参数必须是 [min, val, max]minmax 不能对调,所以以上代码再实现时做了替换

实际效果如下

四、主动背景色彩变动

尽管色彩能够通过上述形式进行主动变动,然而还是有些有余

  1. 代码量比拟多,有些繁琐,容易混同,特地是前后数字的程序
  2. 只实用于两个色彩的变动,比方多种分段的色彩可能就无奈实现了

背景相比于单纯的色彩来说,有一个十分大的劣势在于多层叠加,如果管制每个背景的大小,不就能够管制最终展现的色彩了吗?

还是下面这个例子,咱们先通过突变绘制两层背景,下面是红色rgb(244 67 54),上面是蓝色rgb(29 125 250),而后通过

background-size来管制每一层的大小,原理是这样的

具体实现如下

num{background: linear-gradient(rgb(244 67 54),rgb(244 67 54)), 
    linear-gradient(rgb(29 125 250), rgb(29 125 250));
  color: #fff;
  background-size: calc((var(--num) - 99) * 100% ), 100%;
}

其实这个计算依据简略,解释一下:

  1. --num 大于等于 100 时,计算结果必定是大于 100% 的,所以下面的红色背景是可见的,整体体现为红色
  2. --num 小于 100 时,计算结果必定是小于等于 0% 的,即便是正数,background-size 也解析为 0%,所以下面的红色背景是不可见的,整体体现为上面的蓝色

理论体现如下

如果心愿实现文字色彩的变动,能够利用到 background-clip

num{background: linear-gradient(rgb(244 67 54),rgb(244 67 54)), 
    linear-gradient(rgb(29 125 250), rgb(29 125 250));
  color: transparent;
  background-size: calc((var(--num) - 99) * 100% ), 100%;
  -webkit-background-clip: text;
}

是不是相比下面的形式简略了许多呢?

五、主动变色的进度条

背景还能够适配多种色彩。接下来看一个文章结尾的案例,实现这样一个能够主动变色的进度条,有这样几条规定:

  1. 当进度小于 30% 时,背景呈红色
  2. 当进度大于 30% 并且 小于 60% 时,背景呈橙色
  3. 当进度大于 60% 并且 小于 90% 时,背景呈蓝色
  4. 当进度大于 90% 时,背景呈绿色

示意如下

假如 HTML 如下

<div class="bar" style="--percent: 50;"></div>

能够通过 CSS 伪类和计数器将 CSS 变量显示在页面,有趣味的能够看看张鑫旭老师的这篇文章:小 tips: 如何借助 content 属性显示 CSS var 变量值(这个案例也是在这个根底上批改的),简略润饰一下

.bar {
  display: flex;
  height: 20px;
  background-color: #f5f5f5;
}
.bar::before {counter-reset: progress var(--percent);
  content: counter(progress) '%\2002';
  display: flex;
  justify-content: end;
  width: calc(var(--percent) * 1%);
  font-size: 12px;
  color: #fff;
  background: #2486ff;
  white-space: nowrap;
}

成果如下

那么该如何依据进度主动变色呢?

原理还是相似的!首先,还是将几个色彩通过突变绘制进去,最初的色彩放在最后面,而后依据 CSS 变量管制背景尺寸就行了,原理示意如下:

因为 background-size 自身有边界限度,当小于 0% 时,依然按 0% 来渲染,所以这里能够不用用 clamp来加以限度,缩小代码量,具体代码实现是这样的

.bar::before{
  /* 其余款式 */
  background-image: linear-gradient(green,green), 
    linear-gradient(#2486ff,#2486ff), 
    linear-gradient(orange, orange),  
    linear-gradient(red, red);
  background-size: calc((var(--percent) - 90) * 100% ) 100%, 
    calc((var(--percent) - 60) * 100% ) 100%,
    calc((var(--percent) - 30) * 100% ) 100%,
    100% 100%;
}

简略看一下外面的逻辑:

  1. --percent 大于 90 时,所有背景的尺寸都是 100%,天然显示 最上层的绿色
  2. --percent 大于 60,小于等于 90 时,只有最上层的绿色尺寸是 0,其余背景尺寸都是 100%,所以显示 第二层的蓝色
  3. --percent 大于 30,小于等于 60 时,下面两层背景尺寸都是 0,上面两层背景尺寸都是 100%,所以显示 第三层的橙色
  4. --percent 小于 30 时,只有最底层的尺寸是 100%,其余都是 0,所以显示 最底层的红色

理论体现如下

背景主动变色曾经实现了,不过数字还有一点小问题,当进度条比拟小时,百分比数字显著放不下了,如下

所以,在这种状况下 应该把百分比数字移到里面来,并且变成红色

移到里面,能够通过 text-indent 属性来实现,文字色彩从红色变成红色(hsl(0,100%,50%)),能够通过亮度来实现,当亮度为 100% 时,任何色彩都会变成红色,因为亮度自身有限度,当超过 100% 时,依然依照 100% 来渲染,这一点能够利用起来,具体实现如下

.bar::before{
  /* 其余款式 */
  --l: max(50%, (var(--percent) - 9 ) * 100%);
  color: hsl(0, 100%, var(--l));
  --offset: clamp(0%, ( var(--percent) - 10 ) * -120% , 120%);
  text-indent: var(--offset);
}

这里的计算原理也和后面一样,大家在这里能够认真斟酌一下。

实际效果如下:

能够看到,当百分比小于 10 时,文字是在内部的,防止了空间有余的状况,十分智能。

残缺代码能够拜访:CSS auto color(codepen.io)

六、总结一下

以上就是对于 CSS 主动变色技术的全部内容了,外围其实就是边界值的灵便计算,是不是十分弱小呢?这里总结一下实现要点:

  1. 实现原理是 CSS 变量 和 calc 计算
  2. clamp 能够限度表达式的区间范畴
  3. 通用外围代码 –x: clamp(10,(var(–y) – 99) * 99,20)
  4. 饱和度能够管制色彩的娇艳水平,当饱和度为 0,就变成灰色了
  5. 齐全管制色彩变动,能够用 rgb 或者 hsl 齐全示意进去,别离进行计算
  6. 以上计划仅实用于两个色彩的切换
  7. 多层背景叠加能够实现多种色彩切换
  8. 多层背景切换的外围在于背景尺寸的管制
  9. 亮度为 100% 时,色彩就变成了红色
  10. 局部属性自身有“阈值”,充分利用这种个性能够缩小区域判断

当然,这种技术不仅仅实用于色彩的变动,只有是数值的变动都能够,比方文章中 text-indent 的切换,充分利用这些小技巧能够让咱们的页面更加灵便,更加粗劣。最初,如果感觉还不错,对你有帮忙的话,欢送点赞、珍藏、转发❤❤❤

欢送关注微信公众号:前端侦探

退出移动版