skip to Main Content

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>

2

Answers


  1. 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>
    Login or Signup to reply.
  2. 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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search