15
头图
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

image-20220417223953275

Is it very conspicuous?

In addition, there is a progress bar that can automatically change color according to the progress, as follows

image-20220421195045775

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:

  1. 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
  2. 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

image-20220422180943620

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

image-20220417224108128

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

image-20220421153927397

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

image-20220421154638527

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

Kapture 2022-04-21 at 15.55.20

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

image-20220421162109881

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:

  1. 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
  2. The parameters supported by clamp must be [min, val, max] , min and max cannot be swapped, so the above code is exchanged when re-implementing

The actual effect is as follows

Kapture 2022-04-21 at 16.43.24

4. Automatic background color change

Although the color can be automatically changed in the above way, there are still some shortcomings

  1. There is a lot of code, some cumbersome and easy to confuse, especially the order of the numbers before and after
  2. 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

image-20220421181904629

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:

  1. 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
  2. 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

Kapture 2022-04-21 at 18.19.56

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

Kapture 2022-04-21 at 18.29.38

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:

  1. When the progress is less than 30%, the background is red
  2. When progress is greater than 30% and less than 60%, the background is orange
  3. When progress is greater than 60% and less than 90%, the background is blue
  4. When progress is greater than 90%, the background is green

The indication is as follows

image-20220421195045775

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

image-20220421200829028

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:

image-20220421223946629

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:

  1. When --percent is greater than 90, the size of all backgrounds is 100%, and the top green is displayed naturally
  2. 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
  3. 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
  4. 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

Kapture 2022-04-21 at 23.00.00

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

image-20220421235719823

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:

Kapture 2022-04-21 at 23.46.59

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:

  1. The implementation principle is CSS variables and calc calculations
  2. clamp can limit the range of the expression
  3. Common core code --x: clamp(10,(var(--y) - 99) * 99,20)
  4. Saturation can control the vividness of the color, when the saturation is 0, it becomes gray
  5. Complete control of color changes, which can be fully represented by rgb or hsl, and calculated separately
  6. The above scheme is only suitable for switching between two colors
  7. Multi-layer background overlay can achieve multiple color switching
  8. The core of multi-layer background switching is the control of background size
  9. At 100% brightness, the color becomes white
  10. 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

XboxYan
18.1k 声望14.1k 粉丝