Search code examples
javascriptjqueryrandombackground-image

Randomly change background image for multiple elements using jquery


I am trying to change the background-image of multiple elements with jquery. The elements are supposed to start with a randomly selected background-image and should then shuffle through randomly selected background-images every 2 seconds.

I have put together this vanilla javascript using other pieces of code that I found while searching for a solution, but I am running into the following problems:

  1. My code only changes the background-image of the first element.
  2. My code starts with a randomly selected background-image but then it just goes through the list of images in order instead of randomly choosing a new image every time it changes.
  3. The background-size value is somehow not applied anymore after the background-image is changed.

Here is my code:

var urls = [
'url(http://placekitten.com/g/150/150)', 
'url(http://placekitten.com/g/200/200)', 
'url(http://placekitten.com/g/250/250)',
'url(http://placekitten.com/g/300/300)',
'url(http://placekitten.com/g/350/350)',
'url(http://placekitten.com/g/400/400)',
'url(http://placekitten.com/g/450/450)'
];
var active = Math.floor(Math.random() * (urls.length));
setInterval(function(){
    document.querySelector('.logo').style.background = urls[active];
    active++;
    if (active == urls.length) active = 0;
}, 2000);
.logo {
  background: url(http://placekitten.com/g/150/150);
  background-size: cover;
  display: inline-block;
  width: 200px;
  height: 200px;
  border: 1px solid red;
  transition: background .5s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="logo"></div>
<div class="logo"></div>
<div class="logo"></div>
<div class="logo"></div>
<div class="logo"></div>
<div class="logo"></div>

And here is the same code in jsfiddle

Please help me get to a jQuery version that fixes my issues.


Solution

  • You can select all items with the class logo and use forEach() to iterate over them like this:

    var urls = [
    'url(http://placekitten.com/g/150/150)', 
    'url(http://placekitten.com/g/200/200)', 
    'url(http://placekitten.com/g/250/250)',
    'url(http://placekitten.com/g/300/300)',
    'url(http://placekitten.com/g/350/350)',
    'url(http://placekitten.com/g/400/400)',
    'url(http://placekitten.com/g/450/450)'
    ];
    var active = Math.floor(Math.random() * (urls.length));
    setInterval(function(){
        let logos = document.querySelectorAll('.logo');
        logos.forEach(function(item) {
           item.style.background = urls[active];
           active++;
           if (active == urls.length) active = 0;
        })
    }, 2000);
    .logo {
      background: url(http://placekitten.com/g/150/150);
      background-size: cover;
      display: inline-block;
      width: 200px;
      height: 200px;
      border: 1px solid red;
      transition: background .5s;
    }
    <div class="logo"></div>
    <div class="logo"></div>
    <div class="logo"></div>
    <div class="logo"></div>

    Update: An additional requirement, as mentioned in the comments to this answer, is to select randomly one of the 4 elements with the class logo and change the background image of this one and iterate through all 4 elements randomly. This can be done as follows:

    var urls = [
      'url(http://placekitten.com/g/150/150)',
      'url(http://placekitten.com/g/200/200)',
      'url(http://placekitten.com/g/250/250)',
      'url(http://placekitten.com/g/300/300)',
      'url(http://placekitten.com/g/350/350)',
      'url(http://placekitten.com/g/400/400)',
      'url(http://placekitten.com/g/450/450)'
    ];
    var active = Math.floor(Math.random() * (urls.length));
    setInterval(function() {
      let rand = Math.floor(Math.random() * 4);
      document.getElementsByClassName('logo')[rand].style.background = urls[active];
      active++;
      if (active == urls.length) active = 0;
      //})
    }, 2000);
    .logo {
      background: url(http://placekitten.com/g/150/150);
      background-size: cover;
      display: inline-block;
      width: 200px;
      height: 200px;
      border: 1px solid red;
      transition: background .5s;
    }
    <div class="logo"></div>
    <div class="logo"></div>
    <div class="logo"></div>
    <div class="logo"></div>

    Update: As mentioned in the comments, it should be prevented that the same image gets randomly updated twice in a row. This is now handled by storing the last updated image in a data-attribute and change the random number in case it is the same as this data-attribute. In addition, there was an issue with background-size: cover. This was solved by changing background to background-image.

    var urls = [
      'url(http://placekitten.com/g/150/150)',
      'url(http://placekitten.com/g/200/200)',
      'url(http://placekitten.com/g/250/250)',
      'url(http://placekitten.com/g/300/300)',
      'url(http://placekitten.com/g/350/350)',
      'url(http://placekitten.com/g/400/400)',
      'url(http://placekitten.com/g/450/450)'
    ];
    var active = Math.floor(Math.random() * (urls.length));
    setInterval(function() {
      let rand = Math.floor(Math.random() * 4);
      if (rand <= 2 && rand == document.getElementsByClassName('logo')[0].getAttribute("data-changed")) {
        rand = rand + 1;
      } else if (rand == 2 && rand == document.getElementsByClassName('logo')[0].getAttribute("data-changed")) {
        rand = rand - 1;
      }
    
      document.getElementsByClassName('logo')[rand].style.backgroundImage = urls[active];
      document.getElementsByClassName('logo')[0].setAttribute("data-changed", rand);
    
      active++;
      if (active == urls.length) active = 0;
      //})
    }, 2000);
    .logo {
      background-image: url(http://placekitten.com/g/150/150);
      background-size: cover;
      display: inline-block;
      width: 200px;
      height: 200px;
      border: 1px solid red;
      transition: background .5s;
    }
    <div class="logo"></div>
    <div class="logo"></div>
    <div class="logo"></div>
    <div class="logo"></div>