mcool
mcool

Reputation: 775

Using linear gradient breaks the CSS animation

I have some images that I am trying to make a slideshow out of. I am using CSS to give a fade in-out effect. Here is an example of some code that DOES work and transitions correctly:

.hero {
  background-image: url('/slideshow_images/1.jpg');
  animation: changeBackground 30s infinite;
  animation-duration: 35s;
  animation-timing-function: ease-in-out;
  -webkit-animation-timing-function: ease-in-out;
}

/* Calculate each background % based on how many photos will be shown and for how long*/
/* We need both urls listed in each group to prevent the screen from flashing between background imgs */
@keyframes changeBackground {
  0%,
  6%,
  12% {
    background-image: url('/slideshow_images/1.jpg'), url('/slideshow_images/2.jpg');
  }
  24%,
  30%,
  36% {
    background-image: url('/slideshow_images/2.jpg'), url('/slideshow_images/3.jpg');
  }
  48%,
  54%,
  60% {
    background-image: url('/slideshow_images/3.jpg'), url('/slideshow_images/4.jpg');
  }
  72%,
  78%,
  84% {
    background-image: url('/slideshow_images/4.jpg'), url('/slideshow_images/1.jpg');
  }
}

However, when I add a linear-gradient to each photo. The smooth transition stops. Now the background changes without any animation whatsoever. It simply changes. Here is an example of the code I tried:

.hero {
    height: calc(100vh - 100px);
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    text-align: center;
    justify-content: center;
    background-image: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)), url('/slideshow_images/1.jpg');
    animation: changeBackground 15s infinite;
    animation-duration: 15s;
    animation-timing-function: ease-in-out;
    -webkit-animation-timing-function: ease-in-out;
}

@keyframes changeBackground {
    0%,
    6%,
    12% {
        background-image: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)), url('/slideshow_images/1.jpg'), url('/slideshow_images/2.jpg');
    }
    24%,
    30%,
    36% {
        background-image: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)), url('/slideshow_images/2.jpg'), url('/slideshow_images/3.jpg');
    }
    48%,
    54%,
    60% {
        background-image: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)), url('/slideshow_images/3.jpg'), url('/slideshow_images/4.jpg');
    }
    72%,
    78%,
    84% {
        background-image: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)), url('/slideshow_images/4.jpg'), url('/slideshow_images/1.jpg');
    }
}

How can I keep the animation like I had in the first snippet, but add a linear-gradient to the images? BTW, the reason I have two image URL's in each group is because this fixed the problem I had where the screen would flash when the background-image changed

Upvotes: 1

Views: 208

Answers (1)

Alvin
Alvin

Reputation: 875

Animations

Animations just work when you define same kind of values. For example this won't work bacause the margin changes from 10px to auto:

/* This will blink */
@keyframes animationTest {
  0%{margin:10px}
  100%{margin:auto}
}

To make it work, the transition should calculate being equivalent, for example px to px:

@keyframes animationTest {
  0%{margin:10px}
  100%{margin:20px}
}

Adding a second background

Said so, mixing gradients with background images will always blink. Your solution is to split the values. This is how to apply a second background property without affecting the previous animation

/* add to .hero relative position */
.hero {
  position: relative;
}

/* Define your second background separately. 
You can also apply an animation */
.hero::after {
  content: "";
  position: absolute;
  left:0;
  right:0;
  top:0;
  background: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4));
}

Upvotes: 1

Related Questions