webta.st.ic
webta.st.ic

Reputation: 5179

Remove class added with hover and animationend on mouseout

I have tried out the transitionend and animationend to change my css after a transition or keyframes animation ends. I made an example with both variants and they worked as expected: I can toggle a class, when a transition or animation ends. On hover, I start the transition/animation and in JavaScript I toggle a class, which changes the background-color, after the transition/animation changes.

The only difference is, that when I do the mouseout and the div goes back to the original state, with transition and transitionend, the class will be removed and the original background-color is visible. For keyframes animations and animationend, the class and background-color stay, also when I do the mouseout. How can I get the same behavoir for the animationend like the transition?

var boxTransition = document.getElementById("transition");
var boxAnimation = document.getElementById("animation");

/* add class after transition ends */
boxTransition.addEventListener("transitionend", changeBackground);

/* add class after keyframes animation ends */
boxAnimation.addEventListener("animationend", changeBackground);

function changeBackground() {
  this.classList.toggle("box--end");
}
.box {
  height: 100px;
  margin-bottom: 30px;
  width: 100px;
}

.box--transition {
  background-color: lightcoral;
  transition: width 0.5s ease-in-out;
}

.box--transition:hover {
  width: 300px;
}

.box--animation {
  background-color: lightblue;
}

.box--animation:hover {
  animation: animateWidth 0.5s ease-in-out;
  animation-fill-mode: forwards;
}

.box--end {
  background-color: gray;
}

@keyframes animateWidth {
  from {
    width: 100px;
  }
  to {
    width: 300px;
  }
}
<div id="transition" class="box box--transition"></div>
<div id="animation" class="box box--animation"></div>

Upvotes: 1

Views: 1193

Answers (2)

Jakupov
Jakupov

Reputation: 1676

I can see 2 options for you. First one is to call changeBackground on boxAnimation.onMouseOut():

boxAnimation.addEventListener("mouseout", changeBackground);

That will change background immediately. Second is to set animation for .box--animation without hover:

@keyframes animateWidth2 {
  from {
    width: 300px;
  }
  to {
    width: 100px;
  }
}
.box--animation {
  animation: animateWidth2 0.5s ease-in-out;
  animation-fill-mode: forwards;
}

That will work like transition, but will happen on start too. To prevent this happen from start you can add .box--hovered class to .box in changeBackground() and add animation to .box--animation.box--hovered instead of just .box--animation. Example for second variant.

Upvotes: 1

Towkir
Towkir

Reputation: 4014

You should note that animation and transition are not the same, Thus event handling here is a bit trikcy.

I am going to explain what happens on both of them.

Transition: It's just the animating part of an element's changing property. Example, it could be width or height or color. It is assigned on :hover usually. Thus, it does not wait for animation if a user takes the mouse out of the element before the transition completes.

On the other hand,

Animation: is a complete set of transition and does not care about the user's mouseout event, once starts, it ends on it's own.

So, here is what you can do. As you assigned the toggle on transitionend it's okay because whenever the user takes the mouse out, transition completes and then the event triggers, but for animation, you should take care of them explicitly.

What I did is, (assuming user will keep the mouse on the element for a few second) added the class once animation has ended (like transitionend) then removed the class once the user takes the mouse out of the element.

Not exactly this is what you should do, but you can now get an idea on what to do and when.

Demo:

var boxTransition = document.getElementById("transition");
var boxAnimation = document.getElementById("animation");

/* add class after transition ends */
boxTransition.addEventListener("transitionend", changeBackground);

/* add class after keyframes animation ends */
boxAnimation.addEventListener("animationend", greyOnStart);
boxAnimation.addEventListener("mouseout", revertOnEnd);

function changeBackground() {
  this.classList.toggle("box--end");
}

function greyOnStart(){
  this.classList.add('box--end');
}

function revertOnEnd(){
  this.classList.remove('box--end');
}
.box {
  height: 100px;
  margin-bottom: 30px;
  width: 100px;
}

.box--transition {
  background-color: lightcoral;
  transition: width 0.5s ease-in-out;
}

.box--transition:hover {
  width: 300px;
}

.box--animation {
  background-color: lightblue;
}

.box--animation:hover {
  animation: animateWidth 0.5s ease-in-out;
  animation-fill-mode: forwards;
}

.box--end {
  background-color: gray;
}

@keyframes animateWidth {
  from {
    width: 100px;
  }
  to {
    width: 300px;
  }
}
<div id="transition" class="box box--transition"></div>
<div id="animation" class="box box--animation"></div>

Upvotes: 4

Related Questions