Home > Software design >  Why wont animation reset and play again after class is added dynamically to the element for the seco
Why wont animation reset and play again after class is added dynamically to the element for the seco

Time:06-26

this code changes the background of the div every time a button is pressed but the new background is supposed to fade in so I set an animation. If you press red, and then another color, it makes the transition the first time, but not from the second on. The background will just appear without animation.

function changit(color) {
 document.getElementById('cont').classList = color;
}
@keyframes appear {
  0% {opacity:0;}
  100% {opacity:1;}
}

#cont {
  position: relative;
  width: 100px;
  height: 100px;
  display: block;
}

#cont::before {
  width: 93%;
  height: 100%;
  position: sticky;
  content: "";
  display: block;
}

.red::before, .blue::before, .black::before { transition: opacity 2s ease;animation:appear 2s; }

.red::before {
  background: url(https://cdn.sstatic.net/Img/teams/teams-illo-free-sidebar-promo.svg) no-repeat;
}

.blue::before {
  background: url(https://www.gravatar.com/avatar/24780fb6df85a943c7aea0402c843737?s=64&d=identicon&r=PG) no-repeat;
}

.black::before {
  background:url(https://cdn.sstatic.net/Sites/stackoverflow/Img/subcommunities/intel.svg?v=0371bf2f3b96) no-repeat;
}
<div id="cont">

</div>
<button onclick="changit('red');">make red</button>
<button onclick="changit('blue');">make blue</button>
<button onclick="changit('black');">make black</button>

isnt the animation supposed to play again if the element changes class? How can I reset the animation to start again every time the element changes class to achieve this effect?

CodePudding user response:

The animation property value actually never changes, with all the classes it's always the same and there is no point in time where it's unset, so it won't fire again.
You need to force the CSS engine sees that it did change. For this you can remove the class altogether force what is called a "reflow", which is when the CSS engine recalculates all the element's boxes in the page, and then only, set the class back:

function changit(color) {
  const elem = document.getElementById('cont');
  elem.classList = "";
  elem.offsetWidth; // force reflow
  elem.classList = color;
}

function changit(color) {
  const elem = document.getElementById('cont');
  elem.classList = "";
  elem.offsetWidth; // force reflow
  elem.classList = color;
}
@keyframes appear {
  0% {opacity:0;}
  100% {opacity:1;}
}

#cont {
  position: relative;
  width: 100px;
  height: 100px;
  display: block;
}

#cont::before {
  width: 93%;
  height: 100%;
  position: sticky;
  content: "";
  display: block;
}

.red::before, .blue::before, .black::before { transition: opacity 2s ease;animation:appear 2s; }

.red::before {
  background: url(https://cdn.sstatic.net/Img/teams/teams-illo-free-sidebar-promo.svg) no-repeat;
}

.blue::before {
  background: url(https://www.gravatar.com/avatar/24780fb6df85a943c7aea0402c843737?s=64&d=identicon&r=PG) no-repeat;
}

.black::before {
  background:url(https://cdn.sstatic.net/Sites/stackoverflow/Img/subcommunities/intel.svg?v=0371bf2f3b96) no-repeat;
}
<div id="cont">

</div>
<button onclick="changit('red');">make red</button>
<button onclick="changit('blue');">make blue</button>
<button onclick="changit('black');">make black</button>

Or, since you're using JS anyway, use the WebAnimations API:

function changit(color) {
  const elem = document.getElementById('cont');
  elem.classList = color;
  elem.animate(
    [ { opacity: 0 }, { opacity: 1 } ],
    { duration: 2000, repeat: 1 }
  );
}

function changit(color) {
  const elem = document.getElementById('cont');
  elem.classList = color;
  elem.animate(
    [ { opacity: 0 }, { opacity: 1 } ],
    { duration: 2000, repeat: 1 }
  );
}
#cont {
  position: relative;
  width: 100px;
  height: 100px;
  display: block;
}

#cont::before {
  width: 93%;
  height: 100%;
  position: sticky;
  content: "";
  display: block;
}

.red::before {
  background: url(https://cdn.sstatic.net/Img/teams/teams-illo-free-sidebar-promo.svg) no-repeat;
}

.blue::before {
  background: url(https://www.gravatar.com/avatar/24780fb6df85a943c7aea0402c843737?s=64&d=identicon&r=PG) no-repeat;
}

.black::before {
  background:url(https://cdn.sstatic.net/Sites/stackoverflow/Img/subcommunities/intel.svg?v=0371bf2f3b96) no-repeat;
}
<div id="cont">

</div>
<button onclick="changit('red');">make red</button>
<button onclick="changit('blue');">make blue</button>
<button onclick="changit('black');">make black</button>

  • Related