Search code examples
javascripthtmlcssevents

mouseenter / mouseleave solution that doesn't trigger when mouse enters the smaller second element positioned in the first element


Here is a simple html+css+js code

var myDiv = document.getElementById('myDiv');

myDiv.addEventListener('mouseenter', function() {
  console.log('Mouse entered the div');
});

myDiv.addEventListener('mouseleave', function() {
  console.log('Unfortunately this message happens when we enter the smaller div');
});
#myDiv {
  width: 300px;
  height: 300px;
  background-color: yellow;
  position: absolute;
}
#smaller {
  border: 1px solid red;
  width: 100px;
  height: 100px;
  position: absolute;
  top: 100px;
  left: 100px;
}
<div>
  <div id="myDiv"></div>
  <div id="smaller">
    
  </div>
</div>

The issue here is mouseleave triggers when the mouse appears above the second element. Any nice and simple solution to avoid that? Tried another events. No luck.

P.S. JS solution is preferable. CSS hover is not the way to go for my case. The important note - divs are on the same level (the second div is not a child of the first div).


Solution

  • One option is to use relatedTarget and a control flag to check if you were entering the smaller div(s).

    var myDiv = document.getElementById('myDiv');
    var inSmall = false;
    
    myDiv.addEventListener('mouseenter', function() {
      if (inSmall) {
        inSmall = false;
        return;
      }
      console.log('Mouse entered the div');
    });
    myDiv.addEventListener('mouseleave', function(e) {
      if (e.relatedTarget.id === 'smaller') {
        inSmall = true;
        return;
      }
      console.log('Unfortunately this message happens when we enter the smaller div');
    });
    #myDiv {
      width: 300px;
      height: 300px;
      background-color: yellow;
      position: absolute;
    }
    
    #smaller {
      border: 1px solid red;
      width: 100px;
      height: 100px;
      position: absolute;
      top: 100px;
      left: 100px;
    }
    <div>
      <div id="myDiv"></div>
      <div id="smaller">
      </div>
    </div>

    If you want mouseenter to trigger again when entering from the smaller div, you can remove the control flag.

    var myDiv = document.getElementById('myDiv');
    
    myDiv.addEventListener('mouseenter', function() {
      console.log('Mouse entered the div');
    });
    myDiv.addEventListener('mouseleave', function(e) {
      if (e.relatedTarget.id === 'smaller') return;
      console.log('Unfortunately this message happens when we enter the smaller div');
    });
    #myDiv {
      width: 300px;
      height: 300px;
      background-color: yellow;
      position: absolute;
    }
    
    #smaller {
      border: 1px solid red;
      width: 100px;
      height: 100px;
      position: absolute;
      top: 100px;
      left: 100px;
    }
    <div>
      <div id="myDiv"></div>
      <div id="smaller">
      </div>
    </div>