This is what you are looking for:
var interval = 4000, collection = document.querySelectorAll('#container>.inner'); for (var i = 0; i < collection.length; i++) { (function(i) { setTimeout(function() { collection[collection.length - i - 1].style.opacity = 0; }, i * interval); })(i) }
#container { position: relative; margin: 0 auto; text-align: center; width: 350px; height: 350px; background-color: rgb(200, 200, 200); } .inner { position: absolute; margin: 0 auto; left: 25px; top: 25px; width: 300px; height: 300px; transition: opacity 4s linear; } #one { background-color: rgb(100, 100, 100); } #two { background-color: rgb(0, 160, 230); } #three { background-color: rgb(0, 255, 130); } #four { background-color: rgb(255, 130, 255); }
<div id="container"> <div class="inner" id="one"></div> <div class="inner" id="two"></div> <div class="inner" id="three"></div> <div class="inner" id="four"></div> </div>
To give it a more natural look (an impression of intent, gestures, liveliness), you need to change linear to make your CSS choice easier:
var interval = 4000, collection = document.querySelectorAll('#container>.inner'); for (var i = 0; i < collection.length; i++) { (function(i) { setTimeout(function() { collection[collection.length - i - 1].style.opacity = 0; }, i * interval); })(i) }
#container { position: relative; margin: 0 auto; text-align: center; width: 350px; height: 350px; background-color: rgb(200, 200, 200); } .inner { position: absolute; margin: 0 auto; left: 25px; top: 25px; width: 300px; height: 300px; transition: opacity 4s cubic-bezier(.6, 0, .3, 1); } #one { background-color: rgb(100, 100, 100); } #two { background-color: rgb(0, 160, 230); } #three { background-color: rgb(0, 255, 130); } #four { background-color: rgb(255, 130, 255); }
<div id="container"> <div class="inner" id="one"></div> <div class="inner" id="two"></div> <div class="inner" id="three"></div> <div class="inner" id="four"></div> </div>
Principle: whenever you want to split an animation (repeat the same animation into collections of elements), the chain of the beginning of one animation beyond the end of the previous one is at least inappropriate. You limit yourself to always waiting for the end of one animation to start the next. But usually you need this behavior when the duration of the action is unknown during the execution of the script. The duration is the same here, so traction is just a useless restriction.
Instead, use setTimeout() for the collection, and in the end you will be able to animate several elements at any time and have better (separate) control over the details of the animation (duration, synchronization function and offset step).
Another big problem with your approach is that you make 20 changes for each element instead of one. CSS animations give you control over animation-duration animation-timing-function (very important for motion tweens) and animation-delay (not used here). In addition, it is smoother and lighter in the browser.
I will give an example below, animating motion instead of opacity:
div { background-color: #ddd; margin-top: 1px; min-height: .5rem; transform: translateX(100%); transition: transform 1s cubic-bezier(.5, 0, .1, 1); } body { overflow-x: hidden; margin: 0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div>
The initial answer, before you notice the free jQuery solution:
div { background-color: #ddd; margin-top: 1px; min-height: .5rem; transition: opacity 300ms cubic-bezier(.4, 0, .2, 1); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div>
Final note: This answer did not even touch on a new (and promising) way of animation: Web Animations Api , because it is still an experimental technology.
WAA animates using the chain, but provides methods for canceling animation requests. It works in all major browsers and can be used with polyfill in older browsers.
It will probably gain immense popularity as soon as Android browsers support it. Until then, the best way to animate is to use CSS animations and transitions that, even if not declaratively, also support canceling a request: you just change the property and it automatically starts a new animation for the same property from its current state, overriding the Old one. The only limitation of CSS at the moment is that it will not calculate the new duration based on how much old part was completed, which is possible in WAA.
WAA combines CSS animation, CSS transitions, and SVG animation into one common set of specifications and provides a unified set of methods for managing animation.