JSFiddle - React, Tailwind, and code Playground

by Sub Lines

HTML

<!-- JQuery 3.3.1 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <div class="image one" data-changed="0"></div>
  <div class="image two"></div>
  <div class="image three"></div>
  <div class="image four"></div>
</div>

CSS

.image {
  background-size: cover;
  display: inline-block;
  width: 200px;
  height: 200px;
  border: 1px solid red;
  transition: opacity 0.4s ease;
}

.one { 
  background-image: url(https://placekitten.com/g/350/150); 
}
.two { 
  background-image: url(https://placekitten.com/g/300/550); 
}
.three { 
  background-image: url(https://placekitten.com/g/400/200); 
}
.four { 
  background-image: url(https://placekitten.com/g/350/750); 
}

.visible {
      opacity: 1;
}

.hidden {
  opacity: 0;
}

JavaScript

var urls = [
  'url(https://placekitten.com/g/350/150)',
  'url(https://placekitten.com/g/200/600)',
  'url(https://placekitten.com/g/550/250)',
  'url(https://placekitten.com/g/700/300)',
  'url(https://placekitten.com/g/300/550)',
  'url(https://placekitten.com/g/400/200)',
  'url(https://placekitten.com/g/350/750)'
];

// Select the next image, may be one of the actual displayed images
var active = Math.floor(Math.random() * (urls.length));


setInterval(function() {
  // Select randomnly the next div to change
  var rand = Math.floor(Math.random() * 4);
  
  // Store this list, so that we only make one call to the page
  // equiv : document.getElementsByClassName('image')
  let images = $('.image');
  
  // equiv : images[0].getAttribute("data-changed")
  let datachanged = images.attr("data-changed");
  
  // This conditions work, but their is a better way of doing it. See comment below the snippet
  if (rand <= 2 && rand == datachanged ) {
    rand += 1;
  } else if (rand >= 2 && rand == datachanged ) {
    rand -= 1;
  }

  // Jquery selector for the targetted div
  let current = $('.image:nth-child('+(rand+1)+')');
  
  // Now we can use JQuery methods, such as toggleClass
  current.toggleClass("visible hidden");
  
  // The fade effect takes 0.4ms, or 400ms
  // So we use a setTimeout to change the bg in 400ms and not immediatly
  // Once the background is changed, the "visible" class we be added
  // If you want to change the duration, remember to also change it in the CSS
  setTimeout(function(){
  
    // equiv : images[rand].style.backgroundImage = urls[active];
    current.css('background-image', urls[active]);
    
    
    images[0].setAttribute("data-changed", rand);
  
    current.toggleClass("hidden visible");
  
  },400); // 400 ms because CSS animation duration is 0.4s

  // Change active value so that the background will not be same next time
  active++;
  
  // Faster way to write if(...) { active = 0 }
  active = (active == urls.length) ? 0...