Search code examples
cssanimationcss-animationsdelay

Chaining CSS animations doesn't respect delay


I have created two animations, fadeIn and fadeOut. I want a set of images to fade out and then the images behind to fade in. However, I want this to repeat infinitely, so one will always fade out as the other fades in.

.top-grid-container > div > picture {
    -webkit-animation-duration: 1s, 1s;
    animation-duration: 1s, 1s;
    -webkit-animation-fill-mode: both;
    animation-fill-mode: both;
    -webkit-animation-iteration-count: infinite, infinite;
    animation-iteration-count: infinite, infinite;
    -webkit-animation-name: fadeOut, fadeIn;
    animation-name: fadeOut, fadeIn;
    -webkit-animation-delay: 4s, 8s;
    animation-delay: 4s, 8s;
    /* animation-timing-function: ease-in, ease-out; */
    width: 100%;
}

.top-grid-container > div > picture:nth-of-type(2) {
    -webkit-animation-name: fadeIn, fadeOut;
    animation-name: fadeIn, fadeOut;
    -webkit-animation-delay: 4s, 8s;
    animation-delay: 4s, 8s;
}

@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}
@keyframes fadeIn{0%{opacity:0}to{opacity:1}}

@-webkit-keyframes fadeOut{0%{opacity:1}to{opacity:0}}
@keyframes fadeOut{0%{opacity:1}to{opacity:0}}
<div class="top-grid-container">
  <div class="top-Adrian-Mole">
    <picture>
      <source srcset="https://loremflickr.com/320/240/dog 1x, https://loremflickr.com/640/480/dog 2x, https://loremflickr.com/1280/480/dog 3x">
      <img src="https://loremflickr.com/320/240/dog" alt="Adrian Mole">
    </picture>
    <picture>
      <source srcset="https://loremflickr.com/320/240/london 1x, https://loremflickr.com/640/480/london 2x, https://loremflickr.com/1280/480/london 3x">
      <img src="https://loremflickr.com/320/240/london" alt="Adrian Mole">
    </picture>          
  </div>
</div>

Initially the animation starts ok, but after the first iteration the delay is no longer respected and it gets into an instant repeat from that point onwards.

Ok I have now found out that the delay is not respected for the iteration but only the first call. So I have tried to "fake it" by using the following code.

/* Animation */
.top-grid-container > div > picture {
    -webkit-animation-duration: 8s, 8s;
    animation-duration: 8s, 8s;
    -webkit-animation-fill-mode: both;
    animation-fill-mode: both;
    -webkit-animation-iteration-count: infinite, infinite;
    animation-iteration-count: infinite, infinite;
    -webkit-animation-name: fadeOut, fadeIn;
    animation-name: fadeOut, fadeIn;
    -webkit-animation-delay: 0, 0;
    animation-delay: 0, 0;
    /* animation-timing-function: ease-in, ease-out; */
    width: 100%;
}

.top-grid-container > div > picture:nth-of-type(2) {
    -webkit-animation-name: fadeIn, fadeOut;
    animation-name: fadeIn, fadeOut;
    -webkit-animation-delay: 0, 0;
    animation-delay: 0, 0;
    -webkit-animation-duration: 4s, 4s;
    animation-duration: 4s, 4s;
}


@-webkit-keyframes fadeIn {
    0% {
        opacity: 0
    }
    25% {
        opacity: 1
    }
    50% {
        opacity: 1
    }
    75% {
        opacity: 1
    }
    100% {
        opacity: 0
    }
}
@keyframes fadeIn {
    0% {
        opacity: 0
    }
    25% {
        opacity: 1
    }
    50% {
        opacity: 1
    }
    75% {
        opacity: 1
    }
    100% {
        opacity: 0
    }
}

@-webkit-keyframes fadeOut {
    0% {
        opacity: 1
    }
    25% {
        opacity: 0
    }
    50% {
        opacity: 0
    }
    75% {
        opacity: 0
    }
    100% {
        opacity: 1
    }
}
@keyframes fadeOut {
    0% {
        opacity: 1
    }
    25% {
        opacity: 0
    }
    50% {
        opacity: 0
    }
    75% {
        opacity: 0
    }
    100% {
        opacity: 1
    }
}
<div class="top-grid-container">
  <div class="top-Adrian-Mole">
    <picture>
      <source srcset="https://loremflickr.com/320/240/dog 1x, https://loremflickr.com/640/480/dog 2x, https://loremflickr.com/1280/480/dog 3x">
      <img src="https://loremflickr.com/320/240/dog" alt="Adrian Mole">
    </picture>
    <picture>
      <source srcset="https://loremflickr.com/320/240/london 1x, https://loremflickr.com/640/480/london 2x, https://loremflickr.com/1280/480/london 3x">
      <img src="https://loremflickr.com/320/240/london" alt="Adrian Mole">
    </picture>          
  </div>
</div>

But in this instance one image fades in and out at a different time to the other. When they are on top of each other this does not sync well at all. To me the code looks directly opposite, but in real life the animations are quite different.


Solution

  • The animation-delay property stands for a delay before the animation starts, not a delay between each iteration of the animation.

    In order to achieve what you want, you can use a single animation doing the fadeIn AND the fadeOut of your images, and delay the animation on the second image.

    .top-grid-container > div > picture {
        -webkit-animation-duration: 10s;
        animation-duration: 10s;
        -webkit-animation-fill-mode: both;
        animation-fill-mode: both;
        -webkit-animation-iteration-count: infinite, infinite;
        animation-iteration-count: infinite, infinite;
        -webkit-animation-name: fadeInAndOut;
        animation-name: fadeInAndOut;
        -webkit-animation-delay: 0;
        animation-delay: 0;
        /* animation-timing-function: ease-in, ease-out; */
        width: 100%;
    }
    
    .top-grid-container > div > picture:nth-of-type(2) {
        -webkit-animation-name: fadeInAndOut;
        animation-name: fadeInAndOut;
        -webkit-animation-delay: 5s;
        animation-delay: 5s;
    }
    
    @-webkit-keyframes fadeInAndOut{0%{opacity:0} 40%{opacity:0} 50% {opacity:1} 90% {opacity:1} 100%{opacity:0}}
    @keyframes fadeInAndOut{0%{opacity:0} 40%{opacity:0} 50% {opacity:1} 90% {opacity:1} 100%{opacity:0}}
    <div class="top-grid-container">
      <div class="top-Adrian-Mole">
        <picture>
          <source srcset="https://loremflickr.com/320/240/dog 1x, https://loremflickr.com/640/480/dog 2x, https://loremflickr.com/1280/480/dog 3x">
          <img src="https://loremflickr.com/320/240/dog" alt="Adrian Mole">
        </picture>
        <picture>
          <source srcset="https://loremflickr.com/320/240/london 1x, https://loremflickr.com/640/480/london 2x, https://loremflickr.com/1280/480/london 3x">
          <img src="https://loremflickr.com/320/240/london" alt="Adrian Mole">
        </picture>          
      </div>
    </div>