CSS counter : Number increment dynamic effect
CSS counter: number increment dynamic effect
CSS counters are variables maintained by CSS. These variables can be increased according to CSS rules to track the number of uses. We can use this feature to adjust the content performance according to the document location, such as displaying the list number.
Because the serial number here is just a decoration, the order is not emphasized. Compared to using real DOM elements to display serial numbers, CSS counters are more concise and flexible. In case the content sequence needs to be adjusted, the serial numbers will not be affected.
Sometimes we will see that some Dashboard interface has the effect of fast scrolling of numbers. How can this effect be achieved? This article will introduce several methods.
JavaScript solution
The easiest way is to use a setInterval
timer, just modify the DOM content regularly. However, in order to achieve a smoother animation effect, it is recommended to use requestAnimationFrame
:
function animateValue(obj, start, end, duration) {
let startTimestamp = null;
const step = (timestamp) => {
if (!startTimestamp) startTimestamp = timestamp;
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
obj.innerHTML = Math.floor(progress * (end - start) + start);
if (progress < 1) {
window.requestAnimationFrame(step);
}
};
window.requestAnimationFrame(step);
}
const obj = document.getElementById("value");
animateValue(obj, 100, 0, 5000);
CSS @keyframes combined with margin
This idea is more interesting. The principle is to arrange the numbers in a row and move the element position through animation to display the numbers in different positions:
<div class="counter">
<div class="numbers">
<div>0</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
<div>10</div>
</div>
</div>
.counter {
width: 100px;
overflow: hidden;
}
.numbers {
width: auto;
display: flex;
animation: countNumber 4s infinite alternate;
animation-timing-function: steps(10);
}
.numbers div {
text-align: center;
flex: 0 0 100px;
}
@keyframes countNumber {
0% {
margin-left: 0px;
}
100% {
margin-left: -1000px;
}
}
CSS Counter Starter Edition
CSS counters use the following properties:
-
counter-reset-Create or reset a counter
-
counter-increment-increment variable
-
content-insert the generated content
-
counter() or counters() function-add the value of the counter to the element
To use a CSS counter, you must first create it with counter-reset. Combining CSS animations @keyframes
and setting different increment values at different stages of the animation can achieve this effect:
<div></div>
div::after {
content: counter(count);
animation: counter 3s linear infinite alternate;
counter-reset: count 0;
}
@keyframes counter {
0% {
counter-increment: count 0;
}
10% {
counter-increment: count 1;
}
20% {
counter-increment: count 2;
}
30% {
counter-increment: count 3;
}
40% {
counter-increment: count 4;
}
50% {
counter-increment: count 5;
}
60% {
counter-increment: count 6;
}
70% {
counter-increment: count 7;
}
80% {
counter-increment: count 8;
}
90% {
counter-increment: count 9;
}
100% {
counter-increment: count 10;
}
}
CSS counter high version
Furthermore, if you dare to use the latest features, there is actually a more beautiful operation, and that is to animate CSS variables. The core of this technique is to set the CSS custom property to an integer type, so that it can be used transition
in the same way as other CSS properties with integer values .
@property --num {
syntax: '<integer>';
initial-value: 0;
inherits: false;
}
div {
transition: --num 1s;
counter-reset: num var(--num);
}
div:hover {
--num: 10000;
}
div::after {
content: counter(num);
}
However, it should be noted that currently only Chrome (or Chromium-core browsers such as Edge and Opera) support @property
syntax, so compatibility is a problem. If your page is only for Chrome (such as the Electron app), you can use it with confidence. Otherwise, use the conservative plan above.
Decimals can also play animation
The variables mentioned above are all required to be integers. Can decimals also support this kind of animation? The answer is yes.
You can convert decimals to integers. The principle of the steps is:
-
Register an integer CSS variable (ie
--number
) and specify the initial valueinitial-value
. -
Round
calc
the value with :--integer: calc(var(--number))
@property --integer {
syntax: "<integer>";
initial-value: 0;
inherits: false;
}
--number: 1234.5678;
--integer: calc(var(--number)); /* 1235 */
If you only need to extract the integer part, you can do this:, you don’t --integer: max(var(--number) - 0.5, 0)
even calc()
need it. A similar method can extract the decimal part.
/* @property --integer */
--number: 1234.5678;
--integer: max(var(--number) - 0.5, 0); /* 1234 */
Complete code:
<div></div>
@property --percent {
syntax: "<number>";
initial-value: 0;
inherits: false;
}
@property --temp {
syntax: "<number>";
initial-value: 0;
inherits: false;
}
@property --v1 {
syntax: "<integer>";
initial-value: 0;
inherits: false;
}
@property --v2 {
syntax: "<integer>";
initial-value: 0;
inherits: false;
}
div {
font: 800 40px monospace;
padding: 2rem;
transition: --percent 1s;
--temp: calc(var(--percent) * 100);
--v1: max(var(--temp) - 0.5, 0);
--v2: max((var(--temp) - var(--v1)) * 100 - 0.5, 0);
counter-reset: v1 var(--v1) v2 var(--v2);
}
div::before {
content: counter(v1) "." counter(v2, decimal-leading-zero) "%";
}
const genNumber = () => {
document.querySelector("div").style.setProperty("--percent", Math.random());
};
setInterval(genNumber, 2000);
setTimeout(genNumber);