1

Trying to loop through 3 images with only showing one at time for 7 seconds, which then disappears and then show the next one in the sequence, then the next image. The loop needs to be infinite without a "transition / fade" delay.

The images are animating GIFs, so trying to line up the timing with the transitions is so far failing to work.

Currently using this:

.images {
  margin: auto;
}

.images img {
  position: absolute;
  -webkit-animation: fade 21s infinite;
  animation: fade 21s infinite;
}

@keyframes fade {
  0% {
    opacity: 1;
  }
  15% {
    opacity: 1;
  }
  25% {
    opacity: 0;
  }
  90% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

-webkit-@keyframes fade {
  0% {
    opacity: 1;
  }
  15% {
    opacity: 1;
  }
  25% {
    opacity: 0;
  }
  90% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

#img1 {
  -webkit-animation-delay: 0s;
  animation-delay: 0s;
}

#img2 {
  -webkit-animation-delay: -7s;
  animation-delay: -7s;
}

#img3 {
  -webkit-animation-delay: -14s;
  animation-delay: -14s;
}
<div class="images">
  <img id="img1" src="https://example.com/gif-1.gif">
  <img id="img2" src="https://example.com/gif-2.gif">
  <img id="img3" src="https://example.com/gif-3.gif">
</div>

Any help would be greatly appriciated

1 Answer 1

2

Here you can define the duration in a variable to control the appearance time of a single image.

I'm using a single set of keyframes, changing the opacity of every image to 1 for ⅓ of the animation-duration (and to 0 for the remaining time).

Unfortunately calc can't be used to define percentages into keyframes, so if you change the number of images you also need to manually change those percentages, as described in the comments inside the code.

Grid display is used as an alternative of position: relative and position: absolute. fetchpriority was used for the first image to increase its priority (since it's the first image of the animation and it has to be loaded soon).

.loop {
   --time: 7s;
   display: grid;
}

/* show animation only if user hasn't set a preference,
   otherwise just show stacked images */
@media (prefers-reduced-motion: no-preference) {
  .loop img {   
    grid-area: 1/1;
    animation: rotate calc(var(--time) * 3) linear 0s infinite;
  }
   
  .loop img:nth-child(2) { animation-delay: calc(var(--time) * -2); }
  .loop img:nth-child(3) { animation-delay: calc(var(--time) * -1); }
}

@keyframes rotate {
   /* 33.33% is (100% / number of images) */
   0%, 33.33% { opacity: 1; }
   /* 33.34% is (100% / number of images) + 0.01 */
   33.34%, 100% { opacity: 0; }  
}
<div class="loop">
  <img src="https://picsum.photos/id/237/300/200/" fetchpriority="high" />
  <img src="https://picsum.photos/id/238/300/200/" />
  <img src="https://picsum.photos/id/239/300/200/" />
</div>

As a side note, for a matter of accessibility, you should give the user the capability to stop every animation longer than 5 seconds since it can potentially provoke seizures. In any case don't rotate images faster than 3 per second.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.