Toniq
Toniq

Reputation: 5016

transitionend fires from inner child

This is the minimum reproducable example. transitionend for 'toggle' hover is firing (which I dont want) and hiding 'a' prematurely.

To reproduce click on toggle after transition ends.

I realize this is happening because toggle is inside a (I cannot change that). Is there a way to stop transitionend on toggle (without detecting which transition happend).

Its getting too complicated, finding bugy for transitionend, I would just rather use setTimeout then (which is little ridicouus for css transition).

var a = document.querySelector('.a')
a.style.display = 'block'
setTimeout(function() {
  a.classList.add('visible')
}, 50)

document.querySelector('.toggle').addEventListener('click', function() {
  console.log('click')
  a.addEventListener('transitionend', function cb(e) {

    console.log('end')
    a.style.display = 'none'

  })
  a.classList.remove('visible')

})
.a {
  position: relative;
  width: 200px;
  height: 200px;
  background: red;
  left: 200px;
  display: none;
  transition: left 1s;
}

.visible {
  left: 0;
}

.toggle {
  transition: color 0.2s;
}

.toggle:hover {
  color: #fff;
}
<div class="a">
  <div class="toggle">
    toggle
  </div>
</div>

Upvotes: 0

Views: 82

Answers (2)

A Haworth
A Haworth

Reputation: 36590

You can sense the transition end on the toggle element and stop it from propagating up to the a element.

var a = document.querySelector('.a')
let t = document.querySelector('.toggle');
t.addEventListener('transitionend', function() {
  event.stopPropagation();
});
a.style.display = 'block'
setTimeout(function() {
  a.classList.add('visible')
}, 50)

document.querySelector('.toggle').addEventListener('click', function() {
  console.log('click')
  a.addEventListener('transitionend', function cb(e) {

    console.log('end')
    a.style.display = 'none'

  })
  a.classList.remove('visible')

})
.a {
  position: relative;
  width: 200px;
  height: 200px;
  background: red;
  left: 200px;
  display: none;
  transition: left 1s;
}

.visible {
  left: 0;
}

.toggle {
  transition: color 0.2s;
}

.toggle:hover {
  color: #fff;
}
<div class="a">
  <div class="toggle">
    toggle
  </div>
</div>

Upvotes: 1

jme11
jme11

Reputation: 17397

No JavaScript is required at all using a keyframe animation. Just specify what the end state is and make sure to set the fill mode to forwards so that the end state is not reset.

.a {
  display: grid;
  font: 2rem sans-serif;
  place-content: center;
  
  position: relative;
  width: 200px;
  height: 200px;
  background: red;
  
  left: 200px;
  opacity: 0;
  animation: slideIn .3s ease-in-out forwards;
}

.toggle {
  transition: color 0.2s;
}

.toggle:hover {
  color: #fff;
}

@keyframes slideIn {  
  to {
    opacity: 1;
    left: 0;
  }
}
<div class="a">
  <div class="toggle">
    toggle
  </div>
</div>

Upvotes: 1

Related Questions