CSS Animation: Number increment effect
The number spinning effect is most definitely possible using CSS3 animations and what's better you can also set the end-point using a small bit of JS and actually get the whole functionality.
Method Explanation:
- A
div
is created such that it will always display only one number by setting its height and width as 1em. Overflow of thediv
is set to hidden so as to make only one line visible. - Within this
div
aspan
containing all the numbers from 1 to 0 is created and is positioned relative to the parent. - Initial position of the
span
is at 0px or 0em but during theanimation
the top position is changed so that thespan
gives the impression of being moved upwards. Because thediv
can display only one number at a time, it gives the spinning effect (or the effect of the other numbers disappearing). - Final position is achieved by setting a fixed top position to each of the
span
elements. 0em means the 1st line is visible (number 1), -2em means the third line becomes visible (number 3) and so on. - Increasing or decreasing the animation duration will make the spin effect happen quickly or slowly. The animation iteration count is set to 5 to produce an illusion that the spinner is spinning multiple times.
Note: Using this method, the spin will look like going the whole circle every-time and not like the JSBin sample in question where a 3 to 4 for the first digit would be just a single step and not a full circle.
div { width: 1em; height: 1em; overflow: hidden; line-height: 1em; display: inline-block;}span { position: relative;}.animate { -webkit-animation: spinit 0.2s 5; -moz-animation: spinit 0.2s 5; animation: spinit 0.2s 5;}@-webkit-keyframes spinit { 0% { top: 0em; } 50% { top: -5em; } 100% { top: -9em; }}@-moz-keyframes spinit { 0% { top: 0em; } 50% { top: -5em; } 100% { top: -9em; }}@keyframes spinit { 0% { top: 0em; } 50% { top: -5em; } 100% { top: -9em; }}
/* Setting the required value to top will make the spinner end at that number */
#digit1 { top: -4em; /* -4em means 5 will be the number */}#digit2 { top: -2em;}#digit3 { top: 0em;}
<div> <span class="animate" id='digit1'>1 2 3 4 5 6 7 8 9 0</span></div><div> <span class="animate" id='digit2'>1 2 3 4 5 6 7 8 9 0</span></div><div> <span class="animate" id='digit3'>1 2 3 4 5 6 7 8 9 0</span></div>
CSS3 Increment Text After Animation Complete
By it's definition, counter-increment is a non-animatable css property - that's why you're not being successful in using it in your animation. You would have to use a javascript function to count the bounces. As the animation duration is 2 seconds, one approach would be to use a set-interval approach and increment your counter every 2 seconds.
document.getElementById('counter').innerHTML = 0;
function increment() {
var x = document.getElementById('counter').innerHTML;
//if we declare the x value as 0, it will keep resetting,
//so instead, put we retrieve the initial value from the span
//and set the variable to that value
x++;
//increase by 1
document.getElementById('counter').innerHTML = x; //set span value
}
setInterval(increment, 2000); //1000ms in 1 sec
* {
font-family: sans-serif;
}
#container {
border-bottom: 3px solid #444;
display: flex;
height: 330px;
width: 100%;
}
#oboing {
align-self: flex-end;
animation-duration: 2s;
animation-iteration-count: infinite;
background-color: black;
height: 200px;
margin: 0 auto 0 auto;
transform-origin: bottom;
width: 200px;
}
#counter {
color: white;
position: relative;
left: 40%;
top: 40%;
font-size: 50px;
}
#oboing {
animation-name: oboing;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
animation-timing-function: cubic-bezier(0.280, 0.840, 0.420, 1);
}
@keyframes oboing {
0% {
transform: scale(1, 1) translateY(0);
}
10% {
transform: scale(1.1, .9) translateY(0)
}
30% {
transform: scale(.9, 1.1) translateY(-100px);
}
50% {
transform: scale(1.05, .95) translateY(0)
}
57% {
transform: scale(1, 1) translateY(-7px);
}
64% {
transform: scale(1, 1) translateY(0)
}
100% {
transform: scale(1, 1) translateY(0);
}
}
body {
background: linear-gradient(191deg, #3a22bd, #ea2b0b);
background-size: 400% 400%;
height: 100vh;
overflow: hidden;
-webkit-animation: Colors 4s ease infinite;
-moz-animation: Colors 4s ease infinite;
-o-animation: Colors 4s ease infinite;
animation: Colors 4s ease infinite;
}
@-webkit-keyframes Colors {
0% {
background-position: 0% 52%
}
50% {
background-position: 100% 49%
}
100% {
background-position: 0% 52%
}
}
@-moz-keyframes Colors {
0% {
background-position: 0% 52%
}
50% {
background-position: 100% 49%
}
100% {
background-position: 0% 52%
}
}
@-o-keyframes Colors {
0% {
background-position: 0% 52%
}
50% {
background-position: 100% 49%
}
100% {
background-position: 0% 52%
}
}
@keyframes Colors {
0% {
background-position: 0% 52%
}
50% {
background-position: 100% 49%
}
100% {
background-position: 0% 52%
}
}
<div id='container'>
<div id='oboing'>
<span id='counter'>0</span>
</div>
</div>
How do I implement number increment animation in CSS
There were two issues with your code:
- As mentioned by @NullDev, you had placed
$text
instead of$elem
in one of yoursetTimeout
s. This was a straightforward typo. - The second issue is with the line:
$(this).find('span').removeClass("static").addClass("up");
Inside setTimeout
, the this
variable is not in the same context as the this
variable outside the setTimeout
. To verify this, you can log:
console.log($(this).find('span') === $elem); // should be false
To fix this, you simply need to replace:
$(this).find('span').removeClass("static").addClass("up");
in your first setTimeout
with:
$elem.removeClass("static").addClass("up");
You can find the working code below:
$(function() {
var $number = 1;
$('#test').click(function() {
var $elem = $(this).find('span');
var $text = $(this).find('span').text();
$number = $number + 1;
setTimeout(function() {
$elem.removeClass("static").addClass("up");
}, 0);
setTimeout(function() {
$elem.text($number);
}, 100);
setTimeout(function() {
$elem.removeClass("up").addClass("down");
}, 100);
setTimeout(function() {
$elem.removeClass("down").addClass("static");
}, 200);
});
});
.up {
display: inline-flex;
opacity: 0;
transform: translate3d(0, -20px, 0);
transition: 0.1s ease-in-out;
}
.down {
display: inline-flex;
opacity: 0;
transform: translate3d(0, 20px, 0);
}
.static {
display: inline-flex;
opacity: 1;
transform: translate3d(0, 0px, 0);
transition: 0.1s ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button" id="test" class="btn btn-sm"><span class="static"> 1</span></button>
CSS3 animation: Number Count Up?
A thorough solution with many CSS-only options for counters is this!
Number increment animation duration slow as numbers increase
Use some easing functions instead of incrementing at a constant rate.
Please note, however, that your total execution time will likely always be at least somewhat inaccurate due to the fact that each increment of the value takes some execution time which is not accounted for using this setTimeout
approach. The problem is exacerbated by higher values.
//No easingfunction constant (duration, range, current) { return duration / range;}
//Linear easingfunction linear (duration, range, current) { return ((duration * 2) / Math.pow(range, 2)) * current;}
//Quadratic easingfunction quadratic (duration, range, current) { return ((duration * 3) / Math.pow(range, 3)) * Math.pow(current, 2);}
function animateValue(id, start, duration, easing) { var end = parseInt(document.getElementById(id).textContent, 10); var range = end - start; var current = start; var increment = end > start? 1 : -1; var obj = document.getElementById(id); var startTime = new Date(); var offset = 1; var remainderTime = 0; var step = function() { current += increment; obj.innerHTML = current; if (current != end) { setTimeout(step, easing(duration, range, current)); } else { console.log('Easing: ', easing); console.log('Elapsed time: ', new Date() - startTime) console.log(''); } }; setTimeout(step, easing(duration, range, start));}
animateValue("value", 0, 10000, constant);animateValue("value2", 0, 10000, linear);animateValue("value3", 0, 10000, quadratic);
<div id="value">100</div><div id="value2">100</div><div id="value3">100</div>
Animate numbers using pure CSS during loading
Not sure it's exactly what you are looking for, but here is an example of something similar using keyframe.
div.a { width: 50px; text-align: right; height: 20px; overflow: hidden;}div.a ul { list-style: none; margin: 0; padding: 0; animation: anim 5s forwards; animation-iteration-count: 1; line-height: 20px;}@keyframes anim { 0% { margin-top: 0; } 1%{ margin-top: -20px; } 4% { margin-top: -20px; } 5% { margin-top: -40px; } 8% { margin-top: -40px; } 9% { margin-top: -60px; } 12% { margin-top: -60px; } 13% { margin-top: -80px; } 16% { margin-top: -80px; } 17% { margin-top: -100px; } 20% { margin-top: -100px; } 21% { margin-top: -120px; } 24% { margin-top: -120px; } 25% { margin-top: -140px; } 28% { margin-top: -140px; } 29% { margin-top: -160px; } 32% { margin-top: -160px; } 33% { margin-top: -180px; } 36% { margin-top: -180px; } 37% { margin-top: -200px; } 40% { margin-top: -200px; } 100% { margin-top: -200px; }}
<div class="a"> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> <li>11</li> </ul></div>
How to animate CSS with a delay between an unknown number of elements
Solution 1: jQuery without CSS
You can use jQuery's animate
and delay
functions to achieve this, it's quite simple, here's the code:
$('.IconAnimate i').each(function(i) { $(this).css('opacity', 0); $(this).delay(1000 * i).animate({ 'opacity': 1.0 }, 450);});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" /><div class="row IconAnimate">
<div class="col-xs-12 col-sm-4 col-lg-2"> <div><i class="fa fa-trademark fa-3x"></i> <h4><strong>TITLE 1</h4> <p>BLA BLA BLA</p> </div> </div>
<div class="col-xs-12 col-sm-4 col-lg-2"> <div><i class="fa fa-paint-brush fa-3x"></i> <h4><strong>TITLE 2</strong></h4> <p>BLA BLA BLA</p> </div> </div>
</div>
Related Topics
Vertical Scrolling in iOS Not Smooth
How to Convert Table Based Layout with Bootstrap "Row" and "Col-*-*"
Sticky Top Div with Absolute Positioning
Svg @Font-Face Works in Svg But Not When Included in a Page
Refactoring and Removing Unused CSS from SASS/Less Files
Top-Left and -Right Corner Rounded in Javafx/Css
Bootstrap 3 Placing Icon Inside Input Field
How to Vertically Align and Stretch Content Using CSS Flexbox
How to Ignore Certain Less Files in Web Essentials Less Compiling? (Bootstrap)
CSS 100Vh Is Too Tall on Mobile Due to Browser Ui
My CSS Gradient Doesn't Stretch, It Repeats
Change Justify-Content Value When Flex Items Overflow Container
How to Style an Single Individual Selectinput Menu in R Shiny