Search code examples
javascripteventsevent-bubbling

Listening to events on stacked elements


If I have three divs stacked on top of each other and I want to listen to the bottom most div on mousemove then I'll only get that event when I'm actually on top of only the bottom most element. If another element lies partly on top of the element I'm listening to the event won't be thrown for that element after I move my mouse over the other element (which only covers my element, I'm still over the original element but now also over the new one).

I've created a jsfiddle to display my dilemma: https://jsfiddle.net/maffelu/o5pmxrgz/2/

HTML:

<div id="one">
</div>
<div id="two">
</div>
<div id="three">
</div>

CSS (stacking the divs slightly on top of each other):

div {
  width: 200px;
  height: 200px;
  position: absolute;
  border: 1px #000 solid;
}

#one {
  top: 20px;
  left: 20px;
  background: red;
}

#two {
  top: 50px;
  left: 50px;
  background: green;
}

#three {
  top: 80px;
  left: 80px;
  background: blue;
}

Javascript:

document.getElementById('one').addEventListener('mouseover', function(e) {
    console.log('one');
});

document.getElementById('two').addEventListener('mouseover', function(e){
console.log('two');
});

document.getElementById('three').addEventListener('mouseover', function(e){
console.log('three');
});

enter image description here

I want to listen to mousemove for all three divs separately, is there a way to keep listening even if you are technically moving your mouse over your element which is just covered?


Solution

  • I found a solution to my problem. I listen to the containing element to all my elements and calculate whenever I'm over the div like this (fiddle https://jsfiddle.net/maffelu/o5pmxrgz/4/):

    HTML:

    <div id="container">
      <div id="one">
      </div>
      <div id="two">
      </div>
      <div id="three">
      </div>
    </div>
    

    Javascript:

    var oneBoundaries = document.getElementById('one').getBoundingClientRect();
    document.getElementById('container').addEventListener('mousemove', function(e) {
        var x = e.clientX;
      var y = e.clientY;
      var insideX = x >= oneBoundaries.left && x <= oneBoundaries.right;
      var insideY = y >= oneBoundaries.top && y <= oneBoundaries.bottom;
    
      if(insideX && insideY){
        console.log('On top of "one"!');
      }
    });