Search code examples
htmlcssanimation

css slideshow image some time flicker and and some time just a blank between slide


I have created a slideshow for my project homepage, but on occasion, the screen simply flashes white and then resumes the slideshow. Could you kindly provide any suggestions? I have been unable to locate a solution on this forum that addresses my issue. I am only utilizing CSS and HTML.

.fade-box {
  height: 100vh;
  width: 100%;
  background-image: url(/images/v-1.jpg);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  transition: 5s;
  animation-name: animate;
  animation-direction: alternate-reverse;
  animation-play-state: running;
  animation-timing-function: ease-in-out;
  animation-duration: 33s;
  animation-fill-mode: forwards;
  animation-iteration-count: infinite;
}

@keyframes animate {
  0% {
    background-image: url(/images/v-2.jpg);
  }
  20% {
    background-image: url(/images/v-3.jpg);
  }
  40% {
    background-image: url(/images/v-4.jpg);
  }
  60% {
    background-image: url(/images/v-5.jpg);
  }
  80% {
    background-image: url(/images/v-6.jpg);
  }
  100% {
    background-image: url(/images/v-7.jpg);
  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />

  <link href="style.css" rel="stylesheet" />

  <title>Document</title>
</head>

<body>
  <div class="fade-box"></div>
</body>

</html>


Solution

  • The problem stems from starting the animation before all the images are loaded.

    Loading a background image doesn't start until it's needed so there is often a pause (a white flash) in the animation to begin with.

    One way round that which keeps the same animation is to ensure the images are all loaded before starting the animation.

    This snippet does this by loading the images each in img elements and testing for the onload event.

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    
      <link href="style.css" rel="stylesheet" />
    
      <title>Document</title>
      <style>
        .fade-box {
          height: 100vh;
          width: 100%;
          background-image: url(https://picsum.photos/id/1015/1024/768);
          background-size: cover;
          background-position: center;
          background-repeat: no-repeat;
          transition: 5s;
          animation-direction: alternate-reverse;
          animation-play-state: running;
          animation-timing-function: ease-in-out;
          animation-duration: 33s;
          animation-fill-mode: forwards;
          animation-iteration-count: infinite;
        }
        
        @keyframes animate {
          0% {
            background-image: url(https://picsum.photos/id/21/1024/768);
          }
          20% {
            background-image: url(https://picsum.photos/id/22/1024/768);
          }
          40% {
            background-image: url(https://picsum.photos/id/23/1024/768);
          }
          60% {
            background-image: url(https://picsum.photos/id/24/1024/768);
          }
          80% {
            background-image: url(https://picsum.photos/id/25/1024/768);
          }
          100% {
            background-image: url(https://picsum.photos/id/26/1024/768);
          }
        }
        
        .imgs {
          position: absolute;
          top: 100vh;
        }
      </style>
    </head>
    
    <body>
      <div class="fade-box"></div>
      <div class="imgs">
        <img src="https://picsum.photos/id/21/1024/768">
        <img src="https://picsum.photos/id/22/1024/768">
        <img src="https://picsum.photos/id/23/1024/768">
        <img src="https://picsum.photos/id/24/1024/768">
        <img src="https://picsum.photos/id/25/1024/768">
        <img src="https://picsum.photos/id/26/1024/768">
      </div>
      <script>
        window.onload = function() {
          document.querySelector('.fade-box').style.display = 'block';
          document.querySelector('.fade-box').style.animationName = 'animate';
          document.querySelector('.imgs').style.display = 'none';
        }
      </script>
    </body>
    
    </html>

    This is a rather sledge-hammer way of doing it, and has the additional problem that an if an image takes a long time to load for example, there is a noticable pause in the animation, or even possibly load never completing.

    As the method requires loading as img elements anyway, you could consider animating those rather than the backgrounds, each using the same keyframes, staggered on starting and going from opacity 0 to 1 and vv.

    Doing this would have the added advantage that different browsers would give the same experience. Currently Edge/Chrome fade background images in and out in keyframes, while Firefox changes them instantly, so to get a fading effect cross-browser you'll have to change the way the images are shown anyway.