Welcome to my public account: Front-end detective
Many times, you will encounter the need for string completion. A typical example is the zero-fill operation in time or date, such as
2021-12-31
2022-03-03
The usual practice is
if (num < 10) {
num = '0' + num
}
Later, native completion methods padStart()
and padEnd()
appeared in JS, as follows
'3'.padStart(2, '0')
// 结果是 ’03‘
'12'.padStart(2, '0')
// 结果是 ’12‘
In fact, this effect can also be achieved in CSS, and there are a variety of solutions, let's take a look, I believe you can have a different experience
1. flex-end alignment
Let's first introduce a relatively easy-to-understand solution, which is also very simple, assuming that the HTML is like this
<span>2</span>
-
<span>28</span>
Under normal circumstances, a monospaced font will also be set, which looks more harmonious and beautiful.
span{
font-family: Consolas, Monaco, monospace;
}
We need to generate a "0" with a pseudo-element before the number
span::before{
content: '0'
}
Next, set a fixed width for the element. Since it is a monospaced font, it can be directly set to 2ch
. Pay attention to this ch
unit, which represents the width of the character 0
(for those interested, you can refer to this article: monospaced font is in Application in web layout and CSS3 ch unit hehe ), and then set right alignment on the line
span{
/**/
display: inline-flex;
width: 2ch;
justify-content: flex-end;
}
The principle is very simple, put 3 characters in a space of 2 characters width, and right-align, will it automatically squeeze out the leftmost 0 ? Then go beyond hiding
The complete code is as follows
span::before{
content: '0'
}
span{
display: inline-flex;
width: 2ch;
justify-content: flex-end;
overflow: hidden;
}
2. Dynamic calculation of CSS variables
Since CSS cannot get the text content of the label, it is necessary to build a CSS variable to pass it on, as follows
<span style="--num:2">2</span>
-
<span style="--num:12">28</span>
After getting the variable through var(--num)
, a series of logical judgments can be made. Then, how to automatically fill in zeros when it is less than 10?
Also we need to generate a "0" with a pseudo-element before the number
span::before{
content: '0'
}
Then, you only need to dynamically hide this pseudo-element according to CSS variables, first set the transparency, as follows
span::before{
/**/
opacity: calc(10 - var(--num));
}
The effect is as follows
The specific logic is
- When
--num
is equal to 10, the calculated value of transparency is 0 , rendering directly according to 0 - When
--num
is greater than 10, the calculated value of transparency is , the negative value of , which will be rendered as 0 - When
--num
is less than 10, the calculated value of transparency is , the value of greater than or equal to 1, which will be rendered according to 1
Therefore, the final performance is that is invisible when it is greater than or equal to 10, and is visible when it is less than 10.
However, this is still a bit problematic, the transparency will not affect the position of the element, as follows
How to eliminate this position? There are many methods, the method of margin-left
is adopted here, as follows
span::before{
/**/
margin-left: clamp(-1ch, calc((9 - var(--num)) * 1ch),0ch);
}
clamp is used here, you can understand it as an interval, there are 3 values [Min, Val, Max]
, the front and back are the minimum and maximum values, and the middle is a variable value (note that this is compared with 9), so the logic here is
- When
--num
is greater than or equal to 10, it is assumed to be 15, the intermediate calc value is calculated as -5ch , and the clamp value is the minimum value -1ch - When
--num
is less than 10, it is assumed to be 5, the intermediate calc value is calculated as 5ch , the clamp value is the maximum value 0ch
Therefore, the final performance is when it is greater than or equal to 10, the margin-left is -1ch, and when it is less than 10, the margin-left is 0
That's more perfect
The complete code is as follows
span::before{
content: '0';
opacity: calc(10 - var(--num));
margin-left: clamp(-1ch, calc((9 - var(--num)) * 1ch),0ch);
}
Third, define the counter style
This effect can also be achieved by using a counter. First, look at the default counter effect. We need to hide the original text and use the counter to display CSS variables through pseudo elements. For this technique, you can refer to this article: Tips: How to Display the CSS var variable value with the help of the content attribute, as follows
span::before{
counter-reset: num var(--num);
content: counter(num);
}
Next, you need to use the second parameter <counter-style> of counter
, the counter style. What is this for? I believe that everyone has used an attribute list-style-type , which is similar to this, and can define the style of the sequence, such as the order of lowercase English letters
list-style-type: lower-latin;
Here we need a counter that automatically fills zeros within 10. There is just one ready-made, called decimal-leading-zero
. The translation is, decimal leading zero
list-style-type: decimal-leading-zero;
Back here, what needs to be done is very simple, just add this parameter, the complete code is as follows
span::before{
counter-reset: num var(--num);
content: counter(num, decimal-leading-zero);
}
The effect is as follows
Fourth, the expansion of the counter
The above counter only works with 2 digits, what if you need 3 digits? For example
001、002、...、010、012、...、098、099、100
padStart
in JS can specify the number of digits after padding
'1'.padStart(3, '0')
// 结果是 ’001‘
'99'.padStart(3, '0')
// 结果是 ’099‘
'101'.padStart(3, '0')
// 结果是 ’101‘
In fact, there is also such a capability in CSS, called @counter-style/pad , strictly speaking, this is the official completion scheme, and the syntax is very similar
pad: 3 "0";
However, this needs to be used on a custom counter, that is, @counter-style , if you are interested, you can refer to this article by Mr. Zhang: CSS @counter-style rules are introduced in detail , here is a brief introduction to the usage, assuming Define a counter called pad-num
, implemented as follows
@counter-style pad-num {
system: extends numeric;
pad: 3 "0";
}
The syntax is as follows: system
here means "system", which is some built-in counters. For example, extends numeric
is used here, the latter numeric
means the digital technology system, and the former extends
means extension, based on this, and then pad: 3 "0"
and JS's The meaning is the same, indicating that the place where there are less than 3 digits is filled with "0"
Then apply it to the counter:
span::before{
counter-reset: num var(--num);
content: counter(num, pad-num);
}
The effect is as follows:
Of course, this compatibility is slightly poor, according to actual needs
The complete code above can be accessed at CSS pad(codepen.io)
Fifth, to summarize
The three CSS string completion methods have been introduced above. Have you learned a few more tricks? Each of these methods has its own advantages and disadvantages, and compare their advantages and disadvantages:
- The first solution is very easy to understand and easy to expand. If you need to complete 3 bits, you only need to change the overall width. The disadvantage is that it relies on monospaced fonts.
- The second scheme is more in line with JS logic and more flexible, but the disadvantage is that the calculation is more verbose, and the fault tolerance of CSS values must also be considered.
- The third solution is recommended by me. It does not require calculation and does not depend on the layout. There may not be many students who know it, and if you want to customize the counter, the compatibility is a bit poor.
Regarding the advantages of CSS implementation, there are many advantages, such as easier maintenance, almost no error reporting, more concise code, etc. If you learn it, use it in your project quickly. Finally, if you think it's good and helpful to you, please like, bookmark, and forward ❤❤❤
Welcome to my public account: Front-end detective
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。