I have a slideshow where pictures crossfade automatically in a loop. It is set so that 3 pictures are scrolling.
Demo in Codepen (http://codepen.io/lopis/pen/VYRoKE)
<section class="crossfade">
<article class="slide">
<img src="http://lorempixel.com/400/200/people" alt="" />
</article>
<article class="slide">
<img src="http://lorempixel.com/400/200/cats" alt="" />
</article>
<article class="slide">
<img src="http://lorempixel.com/400/200/sports" alt="" />
</article>
</section>
The CSS:
$slideDuration: 4; // seconds
$slideNum: 3;
@mixin loop($name, $duration, $delay) {
-webkit-animation: $name #{$duration}s #{$delay}s infinite;
-moz-animation: $name #{$duration}s #{$delay}s infinite;
animation: $name #{$duration}s #{$delay}s infinite;
}
@mixin slide() {
@for $i from 1 through $slideNum {
.slide:nth-child( #{$i} ) {
@include loop( crossfade, ($slideNum * $slideDuration), (($i - 1) * $slideDuration) );
}
}
}
@mixin keyframes() {
@-webkit-keyframes crossfade {
0% {
opacity:1;
}
25% {
opacity:1;
}
33% {
opacity:0;
}
86% {
opacity:0;
}
100% {
opacity:1;
}
}
@keyframes crossfade {
0% {
opacity:1;
}
25% {
opacity:1;
}
33% {
opacity:0;
}
86% {
opacity:0;
}
100% {
opacity:1;
}
}
}
.crossfade {
position: relative;
}
.slide {
position: absolute;
top: 0;
}
.slide:first-child {
position: static;
}
@include slide();
@include keyframes();
Is there a way to make an animation like this that would work with any number of slides using just CSS?
Edit: I understand that such dynamism is not intended in CSS but you can have some dynamic content, like by using calc()
, etc.
Some libraries, as the one suggested in the comments, allow the use of mixins for this task. This is not what I'm looking for as it requires a rebuild of the source.
You can get this using only CSS, using a content responsive technique
Let's set a time for each slide of 2 seconds.
We need to set a staggered delay for every nth child of 2 seconds. That is easily acieved with nth-child.
Now, we need to increase the duration of the transition depending on the number of elements. Using this technique we achieve this easily.
The third issue is managing the fade-out. In the standard approach, that would involve changing the keyframes changing point, and it would be cumbersome. The trick to get this working with much less code, is to make a z-index movement in the animation itself. The elements are moving backward, and then we don't care about their opacity anymore
Example set only for 3 posible number of elements:
.container {
width: 100px;
height: 50px;
position: relative;
margin: 10px;
display: inline-block;
}
.element {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
animation: anim 6s infinite;
}
.element:nth-child(1) {
background-color: lightyellow;
animation-delay: 0s;
}
.element:nth-child(2) {
background-color: lightgreen;
animation-delay: 2s;
}
.element:nth-child(3) {
background-color: pink;
animation-delay: 4s;
}
.element:nth-child(4) {
background-color: lightblue;
animation-delay: 6s;
}
.element:nth-child(5) {
background-color: coral;
animation-delay: 8s;
}
.element:nth-child(6) {
background-color: aliceblue;
animation-delay: 10s;
}
.element:nth-child(7) {
background-color: burlywood;
animation-delay: 12s;
}
.element:nth-child(8) {
background-color: bisque;
animation-delay: 14s;
}
.element:nth-child(9) {
background-color: beige;
animation-delay: 16s;
}
.element:nth-last-child(3):first-child,
.element:nth-last-child(3):first-child ~ .element {
animation-duration: 6s;
}
.element:nth-last-child(6):first-child,
.element:nth-last-child(6):first-child ~ .element {
animation-duration: 12s;
}
.element:nth-last-child(9):first-child,
.element:nth-last-child(9):first-child ~ .element {
animation-duration: 18s;
}
@keyframes anim {
0% { opacity: 0; z-index: 100;}
15% { opacity: 1;}
50% { opacity: 1;}
100% { opacity: 0; z-index: 1;}
}
<div class="container">
<div class="element">ONE</div>
<div class="element">TWO</div>
<div class="element">THREE</div>
</div>
<div class="container">
<div class="element">ONE</div>
<div class="element">TWO</div>
<div class="element">THREE</div>
<div class="element">FOUR</div>
<div class="element">FIVE</div>
<div class="element">SIX</div>
</div>
<div class="container">
<div class="element">ONE</div>
<div class="element">TWO</div>
<div class="element">THREE</div>
<div class="element">FOUR</div>
<div class="element">FIVE</div>
<div class="element">SIX</div>
<div class="element">SEVEN</div>
<div class="element">EIGHT</div>
<div class="element">NINE</div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With