文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

我们一起聊聊 CSS 变量自动变色技术

2024-12-02 02:59

关注

是不是非常醒目呢?

另外,还有那种可以根据进度自动变色的进度条,如下:

其实通过纯 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],前后分别是最小、最大值,中间是动态值,这里其实就是一个简单的线性函数,并且单调递增,所以这里的逻辑就是:

当--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 判断的基本原理了,用到了一点点数学运算,接下来看实战效果

二、通过饱和度变化

首先简单布局一下;

由于纯 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%);
color: hsl(27 var(--s) 36%);
}

逻辑和前面一致,这就不重复了,实际效果如下:

Kapture 2022-04-21 at 15.55.20

由于饱和度本身也有“阈值”,当饱和度低于 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);
--g: clamp(67, (var(--num) - 100) * -999 + 67 , 125);
--b: clamp(54, (var(--num) - 100) * -999 + 54 , 250);
color: rgb(var(--r) var(--g) var(--b));
}

需要注意几点:

实际效果如下:

Kapture 2022-04-21 at 16.43.24

四、自动背景颜色变化

虽然颜色可以通过上述方式进行自动变化,但是还是有些不雅。

背景相比于单纯的颜色来说,有一个非常大的优势在于多层叠加,如果控制每个背景的大小,不就可以控制最终展示的颜色了吗?

还是上面这个例子,我们先通过渐变绘制两层背景,上面是红色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%;
}

其实这个计算根据简单,解释一下:

实际表现如下:

Kapture 2022-04-21 at 18.19.56

如果希望实现文字颜色的变化,可以利用到 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;
}

Kapture 2022-04-21 at 18.29.38

是不是相比上面的方式简单了许多呢?

五、自动变色的进度条

背景还可以适配多种颜色。接下来看一个文章开头的案例,实现这样一个可以自动变色的进度条,有这样几条规则:

示意如下:

假设 HTML 如下:

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

可以通过 CSS 伪类和计数器将 CSS 变量显示在页面,有兴趣的可以看看张鑫旭老师的这篇文章:小tips: 如何借助content属性显示CSS var变量值[1](这个案例也是在这个基础上修改的),简单修饰一下。

.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%;
}

简单看一下里面的逻辑:

实际表现如下:

Kapture 2022-04-21 at 23.00.00

背景自动变色已经实现了,不过数字还有一点小问题,当进度条比较小时,百分比数字明显放不下了,如下:

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

移到外面,可以通过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);
}

这里的计算原理也和前面一样,大家在这里可以仔细斟酌一下。

实际效果如下:

Kapture 2022-04-21 at 23.46.59

可以看到,当百分比小于 10 时,文字是在外部的,避免了空间不足的情况,非常智能。

完整代码可以访问:CSS auto color(codepen.io)[2] 或者 CSS auto color(juejin.io)[3]。

六、总结一下

以上就是关于 CSS 自动变色技术的全部内容了,核心其实就是边界值的灵活计算,是不是非常强大呢?这里总结一下实现要点:

当然,这种技术不仅仅适用于颜色的变化,只要是数值的变化都可以,比如文章中text-indent的切换,充分利用这些小技巧可以让我们的页面更加灵活,更加精致。

来源:前端侦探内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯