skip to Main Content

In the attached HTML code that I’ve found on the web to display pictures one-at-a-time every 5 sec with a fade-in/fade-out effect.
The only issue is that at the very beginning all pictures are shown at once and only after the first cycle is completed it performs as expected.
Can anybody advise how to modify the code such that it performs as expected since the beginning?
Thanks.

INDEX.HTML
----------
<!DOCTYPE html>
<html>
<head>
<!-- Comment -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="image-container">
<img src="image1.jpg" style="max-width: 100%; max-height: 100%;" alt="Image 1">
<img src="image2.jpg" style="max-width: 100%; max-height: 100%;" alt="Image 2">
<img src="image3.jpg" style="max-width: 100%; max-height: 100%;" alt="Image 3">
</div>

<script src="script.js"></script>
</body>
</html>

SCRIPT.JS
---------
/* Slide show - Start */
var images = document.getElementById("image-container").children;
var index = 0;

function fadeImages() {
var nextIndex = (index + 1) % images.length;
var currentImage = images[index];
var nextImage = images[nextIndex];

currentImage.style.opacity = 1;

var opacity = 0;
var interval = setInterval(function() {
opacity += 0.05;
nextImage.style.opacity = opacity;
currentImage.style.opacity = 1 - opacity;
if (opacity >= 1) {
  clearInterval(interval);
  currentImage.style.display = "none";
  nextImage.style.display = "block";
  index = nextIndex;
  setTimeout(fadeImages, 5000);
}
}, 50);
}

fadeImages();
/* Slide show - END */

STYLE.CSS
/* Slide show CSS - Start */
#image-container img {
<!--  position absolute; -->
opacity 0;
transition opacity 1s ease-in-out;
}
#image-container imgfirst-child {
opacity 1;
}
/* Slide show CSS - END */

3

Answers


  1. Have all images apart from the first be hidden:

    #image-container img {
      position absolute;
      transition opacity 1s ease-in-out;
    }
    
    #image-container img:not(:first-child) {
      opacity: 0;
      display: none;
    }
    
    /* Slide show - Start */
    var images = document.getElementById("image-container").children;
    var index = 0;
    
    function fadeImages() {
      var nextIndex = (index + 1) % images.length;
      var currentImage = images[index];
      var nextImage = images[nextIndex];
    
      currentImage.style.opacity = 1;
    
      var opacity = 0;
      var interval = setInterval(function() {
        opacity += 0.05;
        nextImage.style.opacity = opacity;
        currentImage.style.opacity = 1 - opacity;
        if (opacity >= 1) {
          clearInterval(interval);
          currentImage.style.display = "none";
          nextImage.style.display = "block";
          index = nextIndex;
          setTimeout(fadeImages, 5000);
        }
      }, 50);
    }
    fadeImages();
    #image-container img {
      position absolute;
      transition opacity 1s ease-in-out;
    }
    
    #image-container img:not(:first-child) {
      opacity: 0;
      display: none;
    }
    <div id="image-container">
      <img src="https://picsum.photos/200/200" style="max-width: 100%; max-height: 100%;" alt="Image 1">
      <img src="https://picsum.photos/200/200?" style="max-width: 100%; max-height: 100%;" alt="Image 2">
      <img src="https://picsum.photos/200/200?0" style="max-width: 100%; max-height: 100%;" alt="Image 3">
    </div>
    Login or Signup to reply.
  2. Let’s first spot some issues:

    • There’s no pleasant cross-fade effect
    • inline HTML style attribute should be avoided for the rare cases when it’s really necessary or logic
    • The CSS is missing : all over the place
    • The imgfirst-child is not a valid selector
    • Avoid hardcoding IDs in JavaScript – such will force you to copy/paste code in order to have multiple slideshows in a single page. Use classes selectors instead. Create a JS class or a function for your slideshow/s
    • Use an active CSS class like .is-active in order to set the styles for the visible image/slide
    • Use clearInterval to allow users to pause the slideshow to enjoy the slide they’re hovering

    Let’s start with removing IDs and using classes instead. Now you can have even multiple

    My cats:
    <div class="image-container">
      <img src="https://placekitten.com/800/587" alt="Image a 1">
      <img src="https://placekitten.com/300/220" alt="Image a 2">
      <img src="https://placekitten.com/400/287" alt="Image a 3">
    </div>
    
    Some more cats:
    <div class="image-container">
      <img src="https://placekitten.com/500/300" alt="Image b 1">
      <img src="https://placekitten.com/360/300" alt="Image b 2">
      <img src="https://placekitten.com/400/400" alt="Image b 3">
      <img src="https://placekitten.com/600/460" alt="Image b 4">
    </div>
    

    Let’s hide all images and use that .is-active styles.
    Remember that if you have position: absolute; children, a parent is better defined also with a position other than static. We’ll use relative:

    .image-container {
      position: relative;   /* anything other than the default static */
      height: 160px;        /* make the parent dictate the height */
    }
    
    .image-container img {
      position: absolute;
      top: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;  /* or use: contain; to make the entire image visible */
      opacity: 0;
      transition: opacity 0.6s ease-in-out;
      pointer-events: none;  /* Prevent mouse actions */
    }
    
    .image-container img.is-active {
      opacity: 1;
      pointer-events: auto;  /* Allow mouse actions */
    }
    

    Now for the JavaScript part.
    Since we have multiple sliders in one page, you could either create a Class, instantiate it passing a desired container ID or simply pass the container Element to your fadeImages(elParent) function.
    See how cleaner and simpler the JS is now:

    const fadeImages = (elContainer) => {
    
      const duration = 3000;
      const elsSlides = elContainer.children;
      const tot = elsSlides.length;
      let idx = 0;
      let itv = null;
      
      const hide = () => elsSlides[idx].classList.remove("is-active");
      const show = () => elsSlides[idx].classList.add("is-active"); 
      const anim = () => {
        hide();
        idx = (idx + 1) % tot;
        show();
      };
      const play = () => itv = setInterval(anim, duration);
      const stop = () => clearInterval(itv);
      
      // Start!
      elContainer.addEventListener("pointerenter", stop);
      show();
      play();
    }
    
    // Init!
    document.querySelectorAll(".image-container").forEach(fadeImages);
    .image-container {
      position: relative;
      height: 160px;
    }
    .image-container img {
      position: absolute;
      top: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
      opacity: 0;
      transition: opacity 1s ease-in-out;
      pointer-events: none; /* Prevent mouse actions */
    }
    
    .image-container img.is-active {
      opacity: 1;
      pointer-events: auto;
    }
    My cats:
    <div class="image-container">
      <img src="https://placekitten.com/800/587" alt="Image a 1">
      <img src="https://placekitten.com/300/220" alt="Image a 2">
      <img src="https://placekitten.com/400/287" alt="Image a 3">
    </div>
    Some more cats:
    <div class="image-container">
      <img src="https://placekitten.com/500/300" alt="Image b 1">
      <img src="https://placekitten.com/360/300" alt="Image b 2">
      <img src="https://placekitten.com/400/400" alt="Image b 3">
      <img src="https://placekitten.com/600/460" alt="Image b 4">
    </div>

    and every slideshow (carousel) runs independently from each other.

    Login or Signup to reply.
  3. var images = document.getElementById("image-container").children;
    let i = images.length-1;
    var interval = setInterval(function(){
      //increase opacity of current image
      if(images[i].style.opacity){
        images[i].style.opacity-=1/50;
      } else images[i].style.opacity = 1.0;
      //if current image invisble then works with next
      if(images[i].style.opacity<=0)i--;
      //if last then stop interval
      if(i==-1)clearInterval(interval)
    },50);
    img{
      position: absolute;
      width: 100%;
      height: 100%;
    }
    <!DOCTYPE html>
    <html>
    <head>
    <!-- Comment -->
    <link rel="stylesheet" href="style.css">
    </head>
    <body>
    <div id="image-container">
      <img src="https://placekitten.com/800/587" alt="Image a 1">
      <img src="https://placekitten.com/300/220" alt="Image a 2">
      <img src="https://placekitten.com/400/287" alt="Image a 3">
    </div>
    
    <script src="script.js"></script>
    </body>
    </html>

    Just tried simplify this task, maybe will be usefull
    *thx roko-c-buljan for cats source

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search