skip to Main Content

Clicking a button should call mobileMenuToggle(), toggling an animation for mobileMenu to either fade in or fade out depending on the current status of the menu screen. When mobileMenu display is none, it should fade in, however when mobileMenu is a block, clicking the button should result in mobile menu fading out. When mobileMenu is active (block), mainBody should disappear. When mainBody is active (block), mobileMenu should disappear. Before any clicks, mobileMenu is set to "display: none"

It works the first two times the button is clicked, but on the third time it breaks. It starts playing only the fadeIn animation but both mobileMenu AND mainBody disappear. I suspect it has something to do with the event listener, but I am not really sure. Any help figuring this out would be greatly appreciated.

JS:

function mobileMenuToggle(){
    if (document.getElementById("mobileMenu").style.display == "none"){
        document.getElementById("mobileMenu").style.animationName = "fadeIn"
        document.getElementById("mobileMenu").style.display = "block"
        document.getElementById("mainBody").style.display = "none"
    }
    else if(document.getElementById("mobileMenu").style.display == "block"){
        document.getElementById("mainBody").style.display = "block"
        document.getElementById("mobileMenu").style.animationName = "fadeOut"
        document.getElementById("mobileMenu").style.display = "block" //trigger animation

        mobileMenu.addEventListener("animationend", () => {
            document.getElementById("mobileMenu").style.display = "none"
          });
    }
}

2

Answers


  1. You are attaching eventlistener every time which causes unwanted behavior. Use once:true:

    mobileMenu.addEventListener("animationend", function() {
            mobileMenu.style.display = "none";
        }, { once: true }); 
    

    Besides I think document.getElementById("mobileMenu").style.display = "block" is unnecessary after fadeOut.

    Login or Signup to reply.
  2. You can use classList property with requestAnimationFrame:

    requestAnimationFrame(() => this.classList.toggle('active'))
    

    requestAnimationFrame allows the passed function to be executed in the
    nearest browser animation frame to ensure smoother and more efficient
    execution of animations and changes on the page.

    Another example: https://dev.to/genakalinovskiy/collapse-with-requestanimationframe-api

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search