I recently needed to crossfade images, showcasing app screens for a project. I looked around online for an ideal solution, and everything I found was way overkill or bloat. I just needed to smoothly faded a series of images into each other. That’s it!

I ended up creating my own with this simple solution. Using javascript setInterval, every few seconds I move (or append) the top item in a list to the bottom, and then letting CSS do the rest.

In the CSS, I set all the items in the list to be stacked on top of each other using position: absolute. Then I set opacity: 0 to all items, except the first-child and last-child. So the top and bottom items are the only two items visible. I also set the first-child (or top item) to have a slightly higher z-index, so they are now stacked in order. As soon as the top item is moved to the bottom, it loses it’s priority z-index but is still visible (just underneath). The 2nd item is then moved to the top, acquiring the new styles of having opacity: 1 and the higher z-index. We now have a working slideshow.

Simply add transition: opacity 1s ease to the first-child and the 2nd item in the list will now fade on top of the item moved to the bottom.

Demo:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Demo without styles:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
HTML
<ul id="crossfade">
  <li style="background: #FF1300">1</li>
  <li style="background: #FF9500">2</li>
  <li style="background: #0BD318">3</li>
  <li style="background: #007AFF">4</li>
  <li style="background: #5856D6">5</li>
  <li style="background: #EF4DB6">6</li>
</ul>  
Javascript
var crossfade = document.getElementById('crossfade');

setInterval(function() {
  var topItem = crossfade.firstChild;
  crossfade.appendChild(topItem);
}, 3000);
Or if you’re using jQuery
setInterval(function(){        
  $('#crossfade li:first-child').appendTo('#crossfade');
}, 3000);
CSS
li {
  position: absolute;
  z-index: 1;
  opacity: 0;
}

li:first-child,
li:last-child {
  opacity: 1;
}

li:first-child {
  z-index: 2;
  transition: opacity 1s ease;
}