Welcome to WeChat public account: front-end detective
I saw such a design on Sifu. When the reading volume is relatively small, the text is gray, and when the reading volume is relatively large (>=100), the text turns brown. The effect is as follows
Is it very conspicuous?
In addition, there is a progress bar that can automatically change color according to the progress, as follows
In fact, such a logical judgment can also be achieved through pure CSS, mainly using CSS variables and boundary value calculation, and now share
1. Basic Mathematical Principles
There is no direct if judgment logic in CSS. To achieve such an effect, one must take full advantage of the computational properties and critical conditions of CSS calc.
Suppose you want to implement such a logic:
--x
The default value is 10, when the variable--y
is greater than or equal to 100,--x
becomes 20
How to achieve it? Here the answer is given first, and then the analysis
--x: clamp(10,(var(--y) - 99) * 99,20)
The clamp
function is used here. You can understand it as an interval with 3 values [Min, Val, Max]
. The front and back are the minimum and maximum values, and the middle is the dynamic value. Here is a simple Linear function and monotonically increasing, so the logic here is:
- When
--y
is less than 100, such as 99, the calculation result of(var(--y) - 99) * 99
is 0, and the smaller value is negative , and the smaller value is taken in the [10, 20] interval, so the final result is 10 - When
--y
is greater than or equal to 100, such as 100, the calculation result of(var(--y) - 99) * 99
is 99, and the larger value is taken in the [10, 20] interval, so the final result is 20
It is represented by a diagram as follows
Why do we need to multiply by 99 here? In fact, it is an operation of enlargement and interpolation . Strictly speaking, in this example, it is enough as long as it is greater than 20. When multiplied by 20, the range becomes ...、-20、0、 20、40、...
, which also includes the interval [10, 20] of.
This is the basic principle of if judgment in CSS. It uses a little mathematical operation. Next, we will see the actual combat effect.
Second, through the saturation change
First simple layout
Since pure CSS cannot get the size of the value, it needs to be calculated with CSS variables, so HTML can be like this
<num style="--num:1">1<span>阅读</span></num>
<num style="--num:99">99<span>阅读</span></num>
<num style="--num:102">102<span>阅读</span></num>
If you don't consider factors such as HTML semantics or SEO , both "numbers" and "reading" here can be generated by pseudo-elements
num::before {
counter-reset: num var(--num);
content: counter(num);
}
num::after {
content: '阅读';
}
Thus, HTML can be further simplified to
<num style="--num:1"></num>
<num style="--num:99"></num>
<num style="--num:102"></num>
The effect after simple modification is as follows
Since it is the change before gray and brown, a simple way is to control it through saturation. For example, the color of brown here is #aa540e
, and the hsl color is hsl(27, 50%, 36%)
, as follows
Here saturation controls how vivid the color is . The higher the saturation, the brighter the color, the lower the saturation, the darker the color, when the saturation is reduced to 0, it becomes a complete gray , as follows
Therefore, to achieve the switching of two colors here, you can calculate the saturation, the specific rule is
When --num
is greater than or equal to 100, the saturation is 85% , otherwise it is 0% , using the basic principles of the previous section, so the implementation is
num{
--s: clamp(0%,(var(--num) - 99) * 99%,85%);/* >100 */
color: hsl(27 var(--s) 36%);
}
The logic is the same as before, so it will not be repeated. The actual effect is as follows
Since the saturation itself also has a "threshold", when the saturation is lower than 0%, it is still rendered at 0% , so the above implementation can remove the minimum value, which is simplified as follows
num{
--s: min((var(--num) - 99) * 99% ,85%);
color: hsl(27 var(--s) 36%);
}
achieve the same purpose
3. Full color control
Although the saturation change control is relatively easy, only one parameter needs to be controlled, but there are still some limitations. First of all, this gray may not be the gray that the designer wants (actually it may be a little lighter), and the color change is not free enough, for example, the default is a blue, and it becomes red when it exceeds a certain amount. Controlled.
Therefore, we need to implement it in a completely analytical way. The principle is to control the three parameters of the color, rgb
or hsl
can be, assuming that the two colors are rgb(29 125 250)
and rgb(244 67 54)
as follows
There are not only increasing changes, but also decreasing changes (for example, 125 => 67, 250 => 54), so it is necessary to negate the calc calculation, the specific implementation is as follows
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));
}
A few things to note:
- The coefficient needs to be large enough, here is 999, such as the first item, when --num is 100, if the coefficient is 99, then the calculated result is 99 + 29, which does not reach the maximum value of 250, so it needs to be larger, such as 999
- The parameters supported by clamp must be
[min, val, max]
,min
andmax
cannot be swapped, so the above code is exchanged when re-implementing
The actual effect is as follows
4. Automatic background color change
Although the color can be automatically changed in the above way, there are still some shortcomings
- There is a lot of code, some cumbersome and easy to confuse, especially the order of the numbers before and after
- Only applies to two color changes, such as multiple segmented colors may not be possible
Compared with the pure color, the background has a very big advantage in that it is superimposed in multiple layers . If you control the size of each background, can you control the color of the final display?
Still the above example, we first draw two backgrounds through gradients, the top is red rgb(244 67 54)
, the bottom is blue rgb(29 125 250)
, and then pass
background-size
to control the size of each layer, the principle is this
The specific implementation is as follows
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%;
}
In fact, this calculation is based on simple, to explain:
- When
--num
is greater than or equal to 100, the calculation result must be greater than 100%, so the red background above is visible, and the overall performance is red - When
--num
is less than 100, the calculation result must be less than or equal to 0%, even if it is a negative number, the background-size is also resolved to 0%, so the red background above is invisible, and the overall performance is as follows blue
The actual performance is as follows
If you want to change the text color, you can use 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;
}
Is it much simpler than the above method?
Five, automatic color-changing progress bar
The background can also be adapted to a variety of colors. Next, let's look at a case at the beginning of the article to implement such a progress bar that can automatically change color. There are several rules:
- When the progress is less than 30%, the background is red
- When progress is greater than 30% and less than 60%, the background is orange
- When progress is greater than 60% and less than 90%, the background is blue
- When progress is greater than 90%, the background is green
The indication is as follows
Suppose the HTML is as follows
<div class="bar" style="--percent: 50;"></div>
You can display CSS variables on the page through CSS pseudo-classes and counters. If you are interested, you can read this article by Mr. Zhang Xinxu: Tips: How to display CSS var variable values with the help of the content attribute (this case is also modified on this basis) , a simple modification
.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;
}
The effect is as follows
So how to automatically change color according to the progress?
The principle is still the same! First, draw several colors through gradients, put the final color at the front, and then control the background size according to CSS variables. The principle is as follows:
Since background-size
has its own boundary limit, when it is less than 0%, it is still rendered at 0%, so there is no need to use clamp
to limit and reduce the amount of code. The specific code implementation is Such
.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%;
}
Just look at the logic inside:
- When
--percent
is greater than 90, the size of all backgrounds is 100%, and the top green is displayed naturally - When
--percent
is greater than 60 and less than or equal to 90, only the green size of the top layer is 0, and the other background sizes are 100%, so the blue of the second layer is displayed - When
--percent
is greater than 30 and less than or equal to 60, the background size of the upper two layers is 0, and the background size of the lower two layers is 100%, so the orange of the third layer is displayed - When
--percent
is less than 30, only the size of the bottom layer is 100%, and the others are 0, so the bottom layer of red is displayed
The actual performance is as follows
The background automatic color change has been realized, but there is still a small problem with the numbers. When the progress bar is relatively small, the percentage figures obviously cannot be put down , as follows
So, in this case the percentage numbers should be moved outside and turned red .
Moving to the outside, it can be achieved by the text-indent
attribute, the text color changes from white to red ( hsl(0,100%,50%)
), and it can be achieved by the brightness, when the brightness is 100%, any color will be It becomes white . Due to the limitation of the brightness itself, when it exceeds 100%, it is still rendered at 100%. This can be used. The specific implementation is as follows
.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);
}
The calculation principle here is the same as before, and you can carefully consider it here.
The actual effect is as follows:
It can be seen that when the percentage is less than 10, the text is outside, which avoids the lack of space and is very smart.
The full code is available at: CSS auto color (codepen.io)
6. To summarize
The above is all about the CSS automatic color changing technology. The core is actually the flexible calculation of the boundary value. Isn't it very powerful? Here is a summary of the implementation points:
- The implementation principle is CSS variables and calc calculations
- clamp can limit the range of the expression
- Common core code --x: clamp(10,(var(--y) - 99) * 99,20)
- Saturation can control the vividness of the color, when the saturation is 0, it becomes gray
- Complete control of color changes, which can be fully represented by rgb or hsl, and calculated separately
- The above scheme is only suitable for switching between two colors
- Multi-layer background overlay can achieve multiple color switching
- The core of multi-layer background switching is the control of background size
- At 100% brightness, the color becomes white
- Some attributes themselves have "thresholds", and making full use of this feature can reduce regional judgments
Of course, this technique is not only suitable for color changes, as long as it is a numerical change, such as the switch in the article text-indent
, making full use of these tips can make our pages more flexible and refined. Finally, if you think it's good and helpful to you, please like, bookmark, and forward ❤❤❤
Welcome to WeChat public account: front-end detective
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。