38

I have an element which is on top of another element. I want to capture the mouseover event with the bottom element, but when the mouse cursor is over the top element the bottom element is not receiving the mouseover events.

Is there any way to disable the top element from receiving mouse events?

tester
  • 619
  • 1
  • 6
  • 5
  • 1
    I've read this several times over and I still don't quite understand what you're asking. Instead of using vague terms like "initial element", can you just say, using the example you've provided, what you'd like the behavior to be? Is your intent to avoid #region2 from having mouse events, or is that a bypass you came up with? **EDIT** I think I get it now, you want the #region2 to stop interfering with #region's mouseover, correct? (Sorry, coffee deprivation) – Brad Christie Nov 29 '10 at 16:28
  • Yes, Brad you are right, thank you for your attention! – tester Nov 29 '10 at 16:35
  • Possible duplicate of [HTML/CSS: Make a div "invisible" to clicks?](https://stackoverflow.com/questions/3538489/html-css-make-a-div-invisible-to-clicks) –  Jul 12 '17 at 19:12

2 Answers2

78

Elements can be easily disabled from receiving mouse events using, in your example, the following CSS:

#region2 {
    pointer-events: none;
}

For more discussion, see this SO post.

Community
  • 1
  • 1
Ryan Rapp
  • 1,583
  • 13
  • 18
  • 4
    +1 thank you very much for this nice and easy solution :) It solved my problem with popup on `OpenLayers` which I show on `mouseover` a marker. – Boro Jun 26 '12 at 08:59
  • Tried everything in the jQuery/css library until I found this. Worked a charm. – Nathan Hangen Feb 19 '13 at 22:46
  • What about keyboard events while the object has focus? Note, this has been easy to do in ActionScript 3 for a decade now (http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/InteractiveObject.html#mouseEnabled) "Specifies whether this object receives mouse, or other user input, messages.", and still seemingly impossible in JavaScript. WTaF? The DOM pails in comparison to AS3 display hierarchy in Flash (InteractiveObject > DisplayObject > EventDispatcher). CSS "pointer-events" seems to be a rip-off of AS3's mouseEnabled, but failing to disable other input events. – Triynko Jan 25 '17 at 20:36
  • Note that if the pointer-events on the elements is set to none, then you can't interact with it, for example, if there is a hyperlink, it can't be clicked. – Ariona Rian Feb 06 '17 at 03:10
  • Amazing! I was searching for this in Javascript for hours! CSS was the last place I would expect to find an answer! – Ramtin Soltani Jul 27 '17 at 10:25
  • 1
    Thanks! exactly what i needed – JonLOo Dec 15 '20 at 16:01
0

This is the best I can come up with. You could probably get pretty elaborate, but (to my knowledge) the greater z-index is always going to capture the event. You CAN, however, work around it but you're probably better off refactoring in to another function with either a supplied (or unsupplied) offset value so you can keep '#region' in mind when the events are transpiring. You can also use e.target to check what is sending you the event (see http://api.jquery.com/category/events/ for more properties)

$('#region2').mousemove(function(e){
  var regionPos = $('#region').position();
  var region2Pos = $('#region').position();
  var offset = {
    left: region2Pos.left - regionPos.left,
    top: region2Pos.top - regionPos.top
  };

  var pageCoords = "( " + e.pageX + ", " + e.pageY + " )";
  var clientCoords = "( " + (e.clientX + offset.left) + ", " + (e.clientY + offset.top) + " )";
  $("span:first").text("( e.pageX, e.pageY ) - " + pageCoords);
  $("span:last").text("( e.clientX, e.clientY ) - " + clientCoords);
});

edit second solution:

<!DOCTYPE html>
<html>
<head>
  <style>
  #region { width:220px; height:170px; margin;10px; margin-right:50px;
        background:yellow; border:2px groove; float:right; }
  #region2 {
    background-color: white;
    float:right;
    position: relative;
    right: -150px; top: 50px;
    width: 100px; height: 100px;
    border: 1px solid
  }

  #region3 {
    width:30px;
    height: 30px;
    background-color: brown;
  }

  p { margin:0; margin-left:10px; color:red; width:220px;
      height:120px; padding-top:70px;
      float:left; font-size:14px; }
  span { display:block; }
  </style>
  <script src="http://code.jquery.com/jquery-1.4.4.js"></script>
  <script type="Text/javascript">
    jQuery.extend({
      MousemoveElement: function(needle,onActivation){
        var elList = needle;
        $('*').mousemove(function(e){
          $('#outside').html('<b>Outside:<b/><br />target: '+e.target.tagName+' ['+e.target.id+']<br />client: '+e.clientX+','+e.clientY+'<br />page: '+e.pageX+','+e.pageY);
          $('#inside').html('');

          if (onActivation==null)
            return;// only search if we need to

          $(needle).each(function(){
            $('#meta').html('outside');
            var pt = { x: e.pageX, y: e.pageY };
            var ext = {
              left: $(this).offset().left,
              right: ($(this).offset().left + $(this).innerWidth()),
              top: $(this).offset().top,
              bottom: ($(this).offset().top + $(this).innerHeight())
            };
            $('#meta').html('<b>PT:</b> '+pt.x+','+pt.y+'<br /><b>EXT:</b> ('+ext.left+','+ext.top+';'+ext.right+','+ext.bottom+')');
            if ((pt.x >= ext.left) && (pt.x <= ext.right) && (pt.y >= ext.top) && (pt.y <= ext.bottom)){
              $('#meta').html('GOOD');
              onActivation(e,$(this));
            }
          });
        });
      }
    });

    $(document).ready(function(){
      $.MousemoveElement('#region',function(e,element){
        $('#inside').html('<b>Inside:<b/><br />target: '+element.attr('id')+'<br />client: '+e.clientX+','+e.clientY+'<br />page: '+e.pageX+','+e.pageY);
        $('#outside').html('');
      });
    });
  </script>
</head>
<body>
    <p>
      Try scrolling too.
      <span id="meta">Move the mouse over the div.</span>
      <span id="outside">&nbsp;</span>
      <span id="inside">&nbsp;</span>
    </p>

    <div id="region"><div id="region3"></div></div>
    <div id="region2"></div>
</body>
</html>
Brad Christie
  • 100,477
  • 16
  • 156
  • 200
  • Brad, thank you for your willing to help! But I need the logic to be inside of $('#region').mousemove ... E.g. like: $('#region2').mousemove(function(e){ $('#region').trigger(e); }); – tester Nov 29 '10 at 16:45
  • I would recommend making your own jQuery function `jQuery.fn.CustomMousemove = function(myTarget){$(this).mousemove(function(e){ ... }); ... }` then handle your own actions based on what's selected. Then you can have all the code in one conclusive area and call `$('#region,#region2').CustomMousemove('#region');` and have all activities affect only #region. – Brad Christie Nov 29 '10 at 19:19
  • Well, Brad, thanks again. The actual problem is to make $('#region').mousemove be executed whenever the mouse moves over its body even if it is behind thousands absolutely positioned divs... I don't think there is any means to do that, however I may not know the solution... – tester Nov 29 '10 at 19:40
  • Well, after some research, it seems to me the only solution is to move all those top divs inside the #region – tester Nov 29 '10 at 21:07
  • Brad... I'm sorry to tell you, but such solution will eat a lot of CPU resources... Check the CPU usage while hovering the mouse pointer anywhere. The mouseover should not be always binded and to so many elements. – tester Nov 30 '10 at 09:22
  • More so a work-around than a solution. Don't know what else to tell you though, just shy of checking when it's over an element's real-estate, I don't see any other way of bypassing an element with a greater z-index. – Brad Christie Nov 30 '10 at 14:29