JSFiddle - React, Tailwind, and code Playground

by Sub Lines

HTML

<div id="images">
  <div class="image"></div>
  <div class="image"></div>
  <div class="image"></div>
  <div class="image"></div>
  <div class="image"></div>
  <div class="image"></div>
  <div class="image"></div>
  <div class="image"></div>
</div>

CSS

body {
  margin: 0;
  font-size: 0;
}

.image {
  background-size: cover;
  display: inline-block;
  width: 23%;
  padding-top: 23%;
  margin: 1%;
}

JavaScript

var urls = [
  'https://source.unsplash.com/5E5N49RWtbA/300x300',
  'https://source.unsplash.com/G85VuTpw6jg/300x300',
  'https://source.unsplash.com/fIq0tET6llw/300x300',
  'https://source.unsplash.com/P_0R02ArdLE/300x300',
  'https://source.unsplash.com/PC_lbSSxCZE/300x300',
  'https://source.unsplash.com/nptLmg6jqDo/300x300',
  'https://source.unsplash.com/1_CMoFsPfso/300x300',
  'https://source.unsplash.com/mk7D-4UCfmg/300x300',
  
  'https://source.unsplash.com/3biD4LTasgY/300x300',
  'https://source.unsplash.com/ZyM1SIGWpCI/300x300',
  'https://source.unsplash.com/zw3ExyW6x3Y/300x300'
];

// Get reference to divs and assign images on inital load
const images = $('.image');
images.each(function(i, e) {
  jQuery(this).css('background-image', `url(${urls[i]})`);
  jQuery(this).data("image-index", i);
});

setInterval(function() {
  // Get indexes that are already in ue
  const usedIdx = images.map(function(i, e) {
    return jQuery(e).data("image-index");
  }).get();
	
	// Filter indexes of urls that are not displayed yet
  const unusedIdx = [];
  urls.forEach(function(url, i) {
    if (usedIdx.indexOf(i) == -1)
      unusedIdx.push(i);
  });
	
	// Choose a random index from the unused indexes array
  const randUnsedIdx = Math.floor(Math.random() * unusedIdx.length);
	
	// Chose a random image div to apply image to
  const randDivIdx = Math.floor(Math.random() * images.length);
  const current = images.eq(randDivIdx);
	
	// Get index number
  const imgUrlIdx = unusedIdx[randUnsedIdx];
	
	// fade out old image then on callback set the url of the new image
	// then fade it in and assign the index to the dive so in next 
	// iteration we can filter it out
  current.fadeOut(400, function() {
    current.css('background-image', `url(${urls[imgUrlIdx]})`);
    current.fadeIn();
    current.data("image-index", imgUrlIdx);
  });

}, 2000);