I managed to achieve this animation through CSS animations and React. but go stuck in flickering problem. I don't know why this is happening maybe 'cause I used setInterval or there is some problem with my css animations keyframes. help me to solve this problem. the flicker only occurs after some time. and after refreshing the page the animation works perfectly fine without flicker problem.
this is how the animation looks after refreshing the page and this is what I want too. (ignore the screen recorder watermark).
animation I want
but after sometime the animation starts flickering like this.
Flickering problem
here are the code snippets I wrote
jsx snippet
<div className="relative w-[280px] md:w-[350px] lg:w-[500px]">
<span>{"[ "}</span>
<p className="text_animate ml-2">
{dev ? "for" : "by"} Developers
</p>
<span className="absolute right-0 ">{" ]"}</span>
</div>
css snippet
.text_animate {
color: orange;
margin: 0 auto;
display: inline-block;
position: relative;
letter-spacing: .15em;
text-align: start;
animation: text-up 6s linear infinite;
cursor: none;
}
#keyframes text-up {
0% {
top:45px;
opacity: 0;
}
20% {
top:0;
opacity: 1;
}
35% {
top: 0;
opacity: 1;
}
50% {
top: -45px;
opacity: 0;
}
52% {
top: 45px;
opacity: 0;
}
70% {
top: 0;
opacity: 1;
}
85% {
top: 0;
opacity: 1;
}
100% {
top: -45px;
opacity: 0;
}
}
useState changing text
const [dev, setDev] = useState(true);
setInterval(() => {
setDev(!dev);
}, 3000);
If there is any better way to achieve this I would really love to learn so let me know that too.
Maybe you should put setInterval to useEffect, and remember to clear timer. Like this:
useEffect(() => {
const timer = setInterval(() => {
setDev(!dev);
}, 3000);
return () => {
clearInterval(timer);
}
}, []);
And there is a solution only using css to implement this, I will write a demo later.
EDIT:
Explain the above code:
useEffect with [] as second param will make sure run setInterval once when mount the component.
The clearInterval in return function will make sure engine GC the variables in setInterval callback functions when unmount the component, or the setInterval will still work even though you needn't it.
CSS only solution:
ul {
margin: 0;
padding: 0;
list-style-type: none;
}
li {
margin: 0;
padding: 0;
}
.scroll-container {
overflow: hidden;
height: calc(var(--line-h) * 1px);
line-height: calc(var(--line-h) * 1px);
font-size: 18px;
}
.scroll-container ul {
animation-name: move;
animation-duration: calc(var(--speed) * var(--lines));
animation-timing-function: steps(var(--lines));
animation-iteration-count: infinite;
}
.scroll-container ul li {
animation-name: li-move;
animation-duration: var(--speed);
animation-iteration-count: infinite;
}
#keyframes move {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(0, calc(var(--lines) * var(--line-h) * -1px));
}
}
#keyframes li-move {
0% {
transform: translate(0, 0);
}
50%,
100% {
transform: translate(0, calc(var(--line-h) * -1px));
}
}
<div
class="scroll-container"
style="--lines: 2; --line-h: 26; --speed: 3s"
>
<ul>
<li>For Developers</li>
<li>By Developers</li>
<!-- repeat first in tail for infinity -->
<li>For Developers</li>
</ul>
</div>
I leaned this from Chokcoco on CodePen but forget which post.
Hello and thank you in advance for reading my question.
GOAL: Set image so that once it's scrolled into view it transitions smoothly into a set position - but still reacts to :hover. Using #keyframes and a little JavaScript, I set the image to opacity: 0 and it's final opacity to opacity: .85. Then I added a hover effect in CSS to make it's opacity: 1
The issue is once it's finished with it's transition - it disappears - reverting to it's original opacity which is zero. I managed to make it freeze at .85 with animation-fill-mode: forwards, rather than animation-fill-mode: none, but then it won't respond to :hover
And here's a test snippet of the problem in action:
let observer_img = new IntersectionObserver(updates => {
updates.forEach(update => {
if (update.isIntersecting) {
update.target.classList.add('shift_frame_center_img');
} else {
update.target.classList.remove('shift_frame_center_img');
}
});
}, { threshold: 0 });
[...document.querySelectorAll('.features-img-wrapper img')].forEach(element => observer_img.observe(element));
body {
width: 100%;
height: 100vh;
background-color: lightgrey;
}
/* CHILD */
.features-img-wrapper img {
width: 10rem;
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 8rem;
opacity: 0;
transition: all .5s;
}
/* APPEND-CHILD */
.shift_frame_center_img {
animation: center_img 1s 0.5s none;
}
/* CHILD ON HOVER */
.features-img-wrapper img:hover {
opacity: 1;
transform: scale(1.035);
}
/* KEYFRAMES */
#keyframes center_img {
0% {
transform: translateY(20rem);
}
100% {
transform: translateY(0);
opacity: .85;
}
}
<body>
<div class="features-img-wrapper">
<img src="https://synapse.it/wp-content/uploads/2020/12/test.png">
</div>
</body>
If I could get a hand with this that would be wonderful, I'm a bit of a beginner and have already spent a few hours on this, all feedback welcome. Thank you very much.
Solution 1
To understand why the hover effect was not working with the animation-fill-mode: forwards, read this answer.
You can fix that by adding !important property to the hover styles:
.features-img-wrapper img:hover {
opacity: 1 !important;
transform: scale(1.035) !important;
}
The problem, in this case, is that the transition will not work for hover.
Solution 2
You could remove the animation entirely and add the final state styles to the shift_frame_center_img class.
But you would still need to use the !important property because of the CSS Specificity.
let observer_img = new IntersectionObserver(updates => {
updates.forEach(update => {
if (update.isIntersecting) {
update.target.classList.add('shift_frame_center_img');
} else {
update.target.classList.remove('shift_frame_center_img');
}
});
}, { threshold: 0 });
[...document.querySelectorAll('.features-img-wrapper img')].forEach(element => observer_img.observe(element));
body {
width: 100%;
height: 100vh;
background-color: lightgrey;
}
/* CHILD */
.features-img-wrapper img {
width: 10rem;
transform: translateY(20rem);
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 8rem;
opacity: 0;
transition: all .5s;
}
/* APPEND-CHILD */
.shift_frame_center_img {
transform: none !important;
opacity: .85 !important;
}
/* CHILD ON HOVER */
.features-img-wrapper img:hover {
opacity: 1 !important;
transform: scale(1.035) !important;
}
<body>
<div class="features-img-wrapper">
<img src="https://synapse.it/wp-content/uploads/2020/12/test.png">
</div>
</body>
This snippet removes the need for fill-mode forwards by setting the img to have opacity 1 as its initial state so it will revert to that at the end of the animation.
The animation itself is altered to take 1.5s rather than 1s with the first third simply setting the img opacity to 0 so it can't be seen. This gives the delay effect.
let observer_img = new IntersectionObserver(updates => {
updates.forEach(update => {
if (update.isIntersecting) {
update.target.classList.add('shift_frame_center_img');
} else {
update.target.classList.remove('shift_frame_center_img');
}
});
}, { threshold: 0 });
[...document.querySelectorAll('.features-img-wrapper img')].forEach(element => observer_img.observe(element));
body {
width: 100%;
height: 100vh;
background-color: lightgrey;
}
/* CHILD */
.features-img-wrapper img {
width: 10rem;
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 8rem;
opacity: 0;
transition: all .5s;
opacity: 1;
}
/* APPEND-CHILD */
.features-img-wrapper img {
animation: center_img 1.5s 0s none;
}
/* CHILD ON HOVER */
.shift_frame_center_img:hover {
opacity: 1;
transform: translateY(0) scale(1.035);
}
/* KEYFRAMES */
#keyframes center_img {
0% {
transform: translateY(20rem) scale(1);
opacity: 0;
}
33.33% {
transform: translateY(20rem) scale(1);
opacity: 0;
}
100% {
transform: translateY(0) scale(1);
opacity: .85;
}
}
<body>
<div class="features-img-wrapper">
<img src="https://synapse.it/wp-content/uploads/2020/12/test.png">
</div>
</body>
Note: as each transform setting will reset anything that isn't included both tranlateY and scale are included in each setting.
Outside the SO snippet system it was possible to leave the animation settings untouched by chaining another animation to the front which ran for 0.5s and just set the img to opacity: 0. This did not work in the snippet system (it got into a loop of flashing on and off) hence the introduction of one but extended animation.
I have a text and I want to apply two different keyframe animations named animeUp and animeDown to it. Also, I want to be able to control the animation using javascript.
The desired result is a javascript line of code to initiate animeUp animation and another one to initiate the animeDown...
I've tried to play and pause the animations by adding CSS classes that change the animation-play-state but using this approach I can only control one of the animations!
Note: we want the keyframe animations as they are...
//pause the animation at first
document.getElementById("Text").classList.add("paused");
//after 2 seconds initiate the animation
setTimeout(function(){
document.getElementById("Text").classList.add("played");
}, 2000)
html{
overflow:hidden;
}
#Text{
position: absolute;
overflow: hidden;
font-family: 'Open Sans', sans-serif;
font-weight: bold;
font-size: 7.5vw;
color: rgb(242, 242, 242);
left: 1vw;
top: -45vh;
animation: animeUp 0.5s ease-out ;
animation: animeDown 0.5s ease-in ;
animation-fill-mode: forwards;
}
#-webkit-keyframes animeUp {
from { top: 10vh }
to { top: -50vh }
}
#-webkit-keyframes animeDown {
from { top: -50vh }
to { top: 10vh }
}
.paused {
-webkit-animation-play-state: paused !important;
}
.played {
-webkit-animation-play-state: running !important;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class = "container">
<p id="Text">Tutorial</p>
</div>
</body>
</html>
Create a class for each animation and toggle between the two.
I threw together a demo, nothing too fancy just to get the idea across.
document.querySelector('.up').onclick = (e) => {
document.getElementById("Text").classList.add("animeup");
document.getElementById("Text").classList.remove("animedown");
e.target.disabled = "true";
document.querySelector('.down').removeAttribute("disabled");
}
document.querySelector('.down').onclick = (e) => {
document.getElementById("Text").classList.remove("animeup");
document.getElementById("Text").classList.add("animedown");
document.querySelector('.up').removeAttribute("disabled");
e.target.disabled = "true";
}
html {
overflow: hidden;
}
#Text {
position: absolute;
overflow: hidden;
font-family: 'Open Sans', sans-serif;
font-weight: bold;
font-size: 7.5vw;
color: red;
left: 1vw;
top: -50vh;
animation-fill-mode: forwards;
}
#-webkit-keyframes animeUp {
from {
top: 10vh
}
to {
top: -50vh
}
}
#-webkit-keyframes animeDown {
from {
top: -50vh
}
to {
top: 10vh
}
}
.animeup {
animation: animeUp 0.5s ease-out;
}
.animedown {
animation: animeDown 0.5s ease-in;
}
<button class="up" disabled>Up</button>
<button class="down">Down</button>
<div class="container">
<p id="Text">Tutorial</p>
</div>
If I set the css animation to "element", it's fine. If the Css animation is not available, how does it function fire like a zero seconds animation in the ES5?
function run() { ... }
element.addEventListener('animationend', run);
Reply for
#Anurag Srivastava,
Am I wrong idea or do I have the following code wrong? Either way, the return value is "".
var el1 = document.getElementById("notAnimation");
console.log(el1.style.animation);
var el2 = document.getElementById("onAnimation");
console.log(el2.style.animation);
div {
padding: 10px;
margin: 20px;
}
#notAnimation {}
#onAnimation {
animation: scale 10s ease-in-out;
}
#keyframes scale {
0% {
transform: scale(1);
opacity: 1;
color: black;
}
50% {
transform: scale(0.95);
opacity: .4;
color: red;
}
100% {
transform: scale(1);
opacity: 1;
color: black;
}
}
<div id="notAnimation">
Not Animation
</div>
<div id="onAnimation">
Animation
</div>
You can check if element.style.WebkitAnimation and element.style.animation contain any value and execute run() if the value is ""
Edit Turns out that .style will return "" for any value. What you need is window.getComputedStyle() along with the property animationName. If it is none, there is no animation, else there is. Check the code below:
var el1 = document.getElementById("notAnimation");
console.log(window.getComputedStyle(el1)["animationName"])
var el2 = document.getElementById("onAnimation");
console.log(window.getComputedStyle(el2)["animationName"])
div {
padding: 10px;
margin: 20px;
}
#notAnimation {}
#onAnimation {
animation: scale 10s ease-in-out;
}
#keyframes scale {
0% {
transform: scale(1);
opacity: 1;
color: black;
}
50% {
transform: scale(0.95);
opacity: .4;
color: red;
}
100% {
transform: scale(1);
opacity: 1;
color: black;
}
}
<div id="notAnimation">
Not Animation
</div>
<div id="onAnimation">
Animation
</div>
As the title implies, is there a proper way to set some initial CSS properties (or class) and tell the browser to transition these to another value?
For example (fiddle):
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
st.transition = 'opacity 2s';
st.opacity = 1;
This will not animate the opacity of the element in Chrome 29/Firefox 23. This is because (source):
[...] you’ll find that if you apply both sets of properties, one immediately
after the other, then the browser tries to optimize the property
changes, ignoring your initial properties and preventing a transition.
Behind the scenes, browsers batch up property changes before painting
which, while usually speeding up rendering, can sometimes have adverse
affects.
The solution is to force a redraw between applying the two sets of
properties. A simple method of doing this is just by accessing a DOM
element’s offsetHeight property [...]
In fact, the hack does work in the current Chrome/Firefox versions. Updated code (fiddle - click Run after opening the fiddle to run animation again):
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
el.offsetHeight; //force a redraw
st.transition = 'opacity 2s';
st.opacity = 1;
However, this is rather hackish and is reported to not work on some android devices.
Another answer suggests using setTimeout so the browser has time to perform a redraw, but it also fails in that we don't know how long it will take for a redraw to take place. Guessing a decent number of milliseconds (30-100?) to ensure that a redraw occurred means sacrificing performance, unnecessarily idling in the hopes that the browser performs some magic in that little while.
Through testing, I've found yet another solution which has been working great on latest Chrome, using requestAnimationFrame (fiddle):
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
requestAnimationFrame(function() {
st.transition = 'opacity 2s';
st.opacity = 1;
});
I assume that requestAnimationFrame waits until right before the beginning of the next repaint before executing the callback, hence the browser does not batch up the property changes. Not entirely sure here, but works nicely on Chrome 29.
Update: after further testing, the requestAnimationFrame method does not work very well on Firefox 23 - it seems to fail most of the time. (fiddle)
Is there a proper or recommended (cross-browser) way of achieving this?
There isn't a clean way at this moment (without using CSS Animations -- see the nearby answer by James Dinsdale for an example using CSS Animations). There is a spec bug 14617, which unfortunately wasn't acted upon since it was filed in 2011.
setTimeout does not work reliably in Firefox (this is by design).
I'm not sure about requestAnimationFrame -- an edit to the original question says it doesn't work reliably either, but I did not investigate. (Update: it looks like requestAnimationFrame is considered at least by one Firefox core developer to be the place where you can make more changes, not necessarily see the effect of the previous changes.)
Forcing reflow (e.g. by accessing offsetHeight) is a possible solution, but for transitions to work it should be enough to force restyle (i.e. getComputedStyle): https://timtaubert.de/blog/2012/09/css-transitions-for-dynamically-created-dom-elements/
window.getComputedStyle(elem).opacity;
Note that just running getComputedStyle(elem) is not enough, since it's computed lazily. I believe it doesn't matter which property you ask from the getComputedStyle, the restyle will still happen. Note that asking for geometry-related properties might cause a more expensive reflow.
More information on reflow/restyle/repaint: http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/
The situation has changed since 2013, so here's a new answer:
You could use Web Animations. They are implemented natively in Chrome 36 and Firefox 40 and there is a polyfill for all the other browsers.
Example code:
var player = snowFlake.animate([
{transform: 'translate(' + snowLeft + 'px, -100%)'},
{transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();
You shouldn't need too much JavaScript to achieve what you want, just use CSS keyframes and animations for the same effect.
div {
opacity: 0;
}
div.fadeIn {
-webkit-animation: fadeIn 2s forwards;
animation: fadeIn 2s forwards;
}
#keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}
#-webkit-keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}
As shown in this JsFiddle it works either from page load (with class already added) or when dynamically adding the class to trigger the animation.
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
$('a.hiw*').click(function(){
id = this.id;
dval = $('#'+id).attr('data-value');
if (dval == 0) {
$('a.hiw*').attr('data-value','0');
$( ".hiw-popup" ).remove();
$('#'+id).attr('data-value','1');
$('<div class="hiw-popup white-well run-animation hidden-xs"><div class="row text-center"><div class="col-sm-2 animation-hiw col-xs-2"><span class="glyphicon glyphicon-pencil hiw-icon1" style="background:#ffffff;">1</span><br/>block1</div><div class="col-sm-2 animation-hiw col-xs-2"><span class="glyphicon glyphicon-shopping-cart hiw-icon2">2</span><br/>BLOCK3</div><div class="col-sm-3 animation-hiw col-xs-3"><span class="glyphicon glyphicon-folder-open hiw-icon3">3</span><br/>BLOCK2</div><div class="col-sm-3 animation-hiw col-xs-3"><span class="glyphicon glyphicon-ok hiw-icon4">4</span><br/>BLOCK</div><div class="col-sm-2 animation-hiw col-xs-2"><span class="glyphicon glyphicon-arrow-down hiw-icon5">5</span><br/>BLOCK</div></div></div>').insertAfter('#'+id);
}else{
$('#'+id).attr('data-value','0');
$( ".hiw-popup" ).remove();
}
});
});
var ahiw = function(id){
dval = $('#'+id).attr('data-value');
if (dval == 0) {
$('a.hiw*').attr('data-value','0');
$( ".hiw-popup" ).remove();
$('#'+id).attr('data-value','1');
$('<div class="hiw-popup white-well run-animation hidden-xs"><div class="row text-center"><div class="col-sm-2 animation-hiw col-xs-2"><span class="glyphicon glyphicon-pencil hiw-icon1" style="background:#ffffff;">1</span><br/>block1</div><div class="col-sm-2 animation-hiw col-xs-2"><span class="glyphicon glyphicon-shopping-cart hiw-icon2">2</span><br/>BLOCK3</div><div class="col-sm-3 animation-hiw col-xs-3"><span class="glyphicon glyphicon-folder-open hiw-icon3">3</span><br/>BLOCK2</div><div class="col-sm-3 animation-hiw col-xs-3"><span class="glyphicon glyphicon-ok hiw-icon4">4</span><br/>BLOCK</div><div class="col-sm-2 animation-hiw col-xs-2"><span class="glyphicon glyphicon-arrow-down hiw-icon5">5</span><br/>BLOCK</div></div></div>').insertAfter('#'+id);
}else{
$('#'+id).attr('data-value','0');
$( ".hiw-popup" ).remove();
}
}
</script>
/* Chrome, Safari, Opera */
#-webkit-keyframes animation-hiw-icon {
from {
background-color: #d9d9d9;
}
to {
background-color: #4ad18f;
}
}
/* Standard syntax */
#keyframes animation-hiw-icon {
from {
background-color: #d9d9d9;
}
to {
background-color: #4ad18f;
}
}
/* Chrome, Safari, Opera */
#-webkit-keyframes animation-hiw-prog {
from {
background-color: #d9d9d9;
width: 0%
}
to {
width: 100%;
background-color: #4ad18f;
}
}
/* Standard syntax */
#keyframes animation-hiw-prog {
from {
width: 0%
}
to {
width: 100%;
}
}
/* Chrome, Safari, Opera */
#-webkit-keyframes animation-hiw-pop {
from {
opacity: 0.5;
background-color: #d9d9d9;
-ms-transform: scale(0.8); /* IE 9 */
-webkit-transform: scale(0.8); /* Chrome, Safari, Opera */
transform: scale(0.8);
}
to {
background-color: #4ad18f;
opacity: 1;
font-weight: normal;
-ms-transform: scale(.8); /* IE 9 */
-webkit-transform: scale(.8); /* Chrome, Safari, Opera */
transform: scale(.8);
}
}
/* Standard syntax */
#keyframes animation-hiw-pop {
from {
background-color: #d9d9d9;
opacity: 0.5;
-ms-transform: scale(0.8); /* IE 9 */
-webkit-transform: scale(0.8); /* Chrome, Safari, Opera */
transform: scale(0.8);
}
to {
background-color: #4ad18f;
opacity: 1;
font-weight: normal;
-ms-transform: scale(.8); /* IE 9 */
-webkit-transform: scale(.8); /* Chrome, Safari, Opera */
transform: scale(.8);
}
}
/*Animation Trigger*/
.run-animation .hiw-progress:after, .run-animation .animation-hiw, .run-animation .hiw-icon1, .run-animation .hiw-icon2, .run-animation .hiw-icon3, .run-animation .hiw-icon4, .run-animation .hiw-icon5 {
-webkit-animation-play-state: running; /* Safari and Chrome */
animation-play-state: running;
}
.run-animation .hiw-progress:after, .run-animation .animation-hiw, .run-animation .hiw-icon1, .run-animation .hiw-icon2, .run-animation .hiw-icon3, .run-animation .hiw-icon4, .run-animation .hiw-icon5 {
-webkit-animation-play-state: running;
animation-play-state: running;
}
.hiw-progress:after {
content: "";
width: 0%;
height: 5px;
background: #4ad18f;
display: inline-block;
position: absolute;
top: 0;
left: 0;
-webkit-animation: animation-hiw-prog 5s linear forwards;
animation: animation-hiw-prog 5s linear forwards;
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
.white-well {
background-color: #fff;
padding: 10px 15px; border-radius: 5px;
border: 1px solid #f1f1f1;
}
.hiw-popup {
position: absolute;
width: 100%;
z-index: 9;
margin: 30px 0 0 -15px;
padding: 0px 15px !important;
border-color: rgba(0, 0, 0, 0.25) !important;
box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.60);
-webkit-box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.60);
-mz-box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.60);
}
.hiw-popup .arrow {
position: absolute;
display: block;
width: 0;
height: 0; border-color: transparent;
border-style: solid;
border-width: 11px;
left:90%;
margin-left: -11px;
border-top-width: 0;
border-bottom-color: rgba(0, 0, 0, 0.25);
top: -11px;
}
.hiw-popup .glyphicon {
margin-bottom: 10px;
margin-right: 0px !important;font-weight:bold;
background-color: #ffffff;color:#222222 !important;
}
.white-well .glyphicon {
background-color: #ffffff!important;
border-radius: 76px;margin-top: -3px;color:#d9d9d9 !important;
padding: 5px 9px 8px;
color: #fff;
box-shadow: 0px 0px 3px #222222;
border: 3px solid #ffffff;
}
.glyphicon {
position: relative;
top: 1px;
display: inline-block;
font-family: 'Glyphicons Halflings';
font-style: normal;
font-weight: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.clearfix:before, .clearfix:after, .container:before, .container:after, .container-fluid:before, .container-fluid:after, .row:before, .row:after, .form-horizontal .form-group:before, .form-horizontal .form-group:after, .btn-toolbar:before, .btn-toolbar:after, .btn-group-vertical > .btn-group:before, .btn-group-vertical > .btn-group:after, .nav:before, .nav:after, .navbar:before, .navbar:after, .navbar-header:before, .navbar-header:after, .navbar-collapse:before, .navbar-collapse:after, .modal-footer:before, .modal-footer:after, .review:before, .review:after, .panel-body:before, .panel-body:after {
content: " ";
display: table;
}
.animation-hiw:nth-child(1) {
-webkit-animation-delay: .2s;
animation-delay: .2s;
}
.hiw-icon5 {
-webkit-animation: animation-hiw-icon 0.2s forwards;
animation: animation-hiw-icon 0.2s forwards;
-webkit-animation-delay: 5s;
animation-delay: 5s;
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
.hiw-icon4 {
-webkit-animation: animation-hiw-icon 0.2s forwards;
animation: animation-hiw-icon 0.2s forwards;
-webkit-animation-delay: 3.75s;
animation-delay: 3.75s;
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
.hiw-icon3 {
-webkit-animation: animation-hiw-icon 0.2s forwards;
animation: animation-hiw-icon 0.2s forwards;
-webkit-animation-delay: 2.25s;
animation-delay: 2.25s;
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
.hiw-icon2 {
-webkit-animation: animation-hiw-icon 0.2s forwards;
animation: animation-hiw-icon 0.2s forwards;
-webkit-animation-delay: 1s;
animation-delay: 1s;
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
.hiw-icon1 {
-webkit-animation: animation-hiw-icon 0.2s forwards;
animation: animation-hiw-icon 0.2s forwards;
-webkit-animation-delay: .2s;
animation-delay: .2s;
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
.animation-hiw {
-webkit-animation: animation-hiw-pop 0.2s forwards; /* Chrome, Safari, Opera */
animation: animation-hiw-pop 0.2s forwards;
-webkit-animation-play-state: paused; /* Safari and Chrome */
animation-play-state: paused;
opacity: 0.5;
-ms-transform: scale(0.8); /* IE 9 */
-webkit-transform: scale(0.8); /* Chrome, Safari, Opera */
transform: scale(0.8);
background: #d9d9d9;
width: 15%;
padding: 2% 1%;
height: 140px;
color: #ffffff; float: left;
}
.animation-hiw:nth-child(1){ -webkit-animation-delay: .2s; animation-delay: .2s; }
.animation-hiw:nth-child(2){ -webkit-animation-delay: 1s; animation-delay: 1s; }
.animation-hiw:nth-child(3){ -webkit-animation-delay: 2.25s; animation-delay: 2.25s; }
.animation-hiw:nth-child(4){ -webkit-animation-delay: 3.75s; animation-delay: 3.75s; }
.animation-hiw:nth-child(5){ -webkit-animation-delay: 5s; animation-delay: 5s; }
hiw {
visibility: hidden;
font-size: 12px;
font-style: italic;
text-align: right;
float: right;
}
<body>
How it works
</body>
#
Here's a working version. See it yourself.
Tested on Chrome, Firefox, Opera.
On my version of firefox, it does not support style.transition so I made it to fallback to vendor specific name if standard name is not available.
http://jsfiddle.net/eNCBz/5/
var el = document.querySelector('div');
var VENDORS = ['Moz', 'Webkit', 'Ms', 'O'];
function getVendorSpecificName(el, prop) {
var style = el.style;
if (prop in style) {
return prop;
}
prop = ucfirst(prop);
for (var i = 0, l = VENDORS.length, name; i < l; i++) {
name = VENDORS[i] + prop;
if (name in style) {
return name;
}
}
return null;
}
function ucfirst(str) {
return str && str.charAt(0).toUpperCase() + str.substring(1);
}
function toCamelCase(str) {
return str.split('-').map(function (str, i) {
return i > 0 ? ucfirst(str) : str;
}).join('');
}
function animateCss(el, prop, from, to, duration) {
var style = el.style,
camel = toCamelCase(prop),
vendorSpecific = getVendorSpecificName(el, camel);
if (!vendorSpecific) {
console.log(prop + ' is not supported by this browser');
return false;
}
var transitionPropName = getVendorSpecificName(el, 'transition');
if (!(transitionPropName in style)) {
console.log('transition is not supported by this browser');
return false;
}
style[vendorSpecific] = from;
setTimeout(function () {
style[transitionPropName] = prop + ' ' + duration + 's ease';
setTimeout(function () {
style[vendorSpecific] = to;
}, 1);
}, 1);
return true;
}
animateCss(el, 'opacity', 0, 1, 2);
Let me explain what is going on:
made some helper functions like ucfirst, toCamelCase
style property uses camel case names
try to find vendor specific style property name if standard name is not available
utilize setTimeout function to make sure browser to redraw
as far as I know, all browsers always redraw on timeout
I tried to make it more generic function so other properties can be applied as well, such as color or background.
Hope this helps!