setTimeout and display none with a fader timer- How to do it chronologically?

Viewed 436

I am sitting with a project in need of an overlay which fades out when hovered upon and goes to display: none (not visibility: hidden, it does need to be display: none).

The setup is a big confusing, but I will try to explain it:

The overlay comes up when I hover a menu point under my mega menu. When I move the cursor to the overlay it should naturally dissapear and the menu close.

This works very well with this code:

var element = document.getElementById("overlayed");

function mouseOver() {

  element.classList.add("mystyle");


  setTimeout(function() {
    element.classList.remove("mystyle");
  }, 500);

}
push {
  position: absolute;
  top: 50%;
}

.overlayerstwo {
  position: fixed;
  width: 100%;
  top: 30%;
  left: 0;
  right: 0;
  bottom: 0;
  background: #111;
  opacity: 0.5;
  z-index: 2;
  display: block;
  visibility: visible;
}

.mystyle {
  display: none;
  animation-name: fadeOut;
  animation-duration: .5s;
}

@keyframes fadeOut {
  0% {
    opacity: .5
  }
  100% {
    opacity: 0;
  }
}

.mystyler {
  display: none;
}
<h1>Here is something. Overlay comes back when hovering me!</h1>
<div class="overlayerstwo" id="overlayed" onmouseover="mouseOver()"></div>
<div class="push">
  <p>Here is an item being overlayed</p>
</div>

With this setup the overlay dissapears right away. I am trying to merge it with the fadeOut keyframe animation before it goes black. I have tried different tactics, like adding a second timeout event but all it does is loop through and end up showing the overlay permanently after.

So the order I want to achieve is as follows:

  • Add a class that fires the keyframe animation fadeOut for .5 sec
  • Remove keyframe animation class
  • Add display: block class
  • Remove display: block class (essentially resetting it, so you can get the overlay up again by hovering its triggerpoint)

So my question is, how do I get all of these to fire every time I hover over the overlay? One of the things I tried was this:

var element = document.getElementById("overlayed");
  element.classList.add("mystyle");
  
setTimeout(function(){
 var element = document.getElementById("overlayed");
  element.classList.remove("mystyle");
}, 500);

setTimeout(function(){
 var element = document.getElementById("overlayed");
  element.classList.add("mystyletwo");
}, 500);

setTimeout(function(){
 var element = document.getElementById("overlayed");
  element.classList.remove("mystyletwo");
}, 510);

With the css

.mystyle{  
    animation-name: fadeOut;
    animation-duration: .5s;
}

.mystyletwo{
    display: block;
}

Which did not work. I hope someone can help me figure out how to get it to work!

1 Answers

if the timeline will be like this:
visible -> hover -> animation -> opacity to 0 -> display: none

using CSS with JS logic:

element.addEventListener("mouseover", function() {
    element.style.opacity = "0";
    element.style.transition = "all 0.3s";

    // when finish the animation then call display none 
    setTimeout(function() {
        element.style.display = "none";
    }, 300); // put the same number (milliseconds) of  duration of transition (or more, not less)
});

using this method you don't need to complex your code...
the trick really is because we use element.style
that is only put the CSS, but technically...
if there is a transition Javascript don't know it,

so it will run the setTimeout() directly after adding styles,
so now CSS will do the animation but javascript will quietly continue the code (which in our case, says that after 300 seconds add display: none;)

Related