通过一个 DIV 单击底层元素

I have a div that has background:transparent, along with border. Underneath this div, I have more elements.

Currently, I'm able to click the underlying elements when I click outside of the overlay div. However, I'm unable to click the underlying elements when clicking directly on the overlay div.

I want to be able to click through this div so that I can click on the underlying elements.

My Problem

转载于:https://stackoverflow.com/questions/3680429/click-through-a-div-to-underlying-elements

Yes, you CAN do this.

Using pointer-events: none along with CSS conditional statements for IE11 (does not work in IE10 or below), you can get a cross browser compatible solution for this problem.

Using AlphaImageLoader, you can even put transparent .PNG/.GIFs in the overlay div and have clicks flow through to elements underneath.

CSS:

pointer-events: none;
background: url('your_transparent.png');

IE11 conditional:

filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='your_transparent.png', sizingMethod='scale');
background: none !important;

Here is a basic example page with all the code.

it doesn't work that way. the work around is to manually check the coordinates of the mouse click against the area occupied by each element.

area occupied by an element can found found by 1. getting the location of the element with respect to the top left of the page, and 2. the width and the height. a library like jQuery makes this pretty simple, although it can be done in plain js. adding an event handler for mousemove on the document object will provide continuous updates of the mouse position from the top and left of the page. deciding if the mouse is over any given object consists of checking if the mouse position is between the left, right, top and bottom edges of an element.

Nope, you can't click ‘through’ an element. You can get the co-ordinates of the click and try to work out what element was underneath the clicked element, but this is really tedious for browsers that don't have document.elementFromPoint. Then you still have to emulate the default action of clicking, which isn't necessarily trivial depending on what elements you have under there.

Since you've got a fully-transparent window area, you'll probably be better off implementing it as separate border elements around the outside, leaving the centre area free of obstruction so you can really just click straight through.

I think that you can consider changing your markup. If I am not wrong, you'd like to put an invisible layer above the document and your invisible markup may be preceding your document image (is this correct?).

Instead, I propose that you put the invisible right after the document image but changing the position to absolute.

Notice that you need a parent element to have position: relative and then you will be able to use this idea. Otherwise your absolute layer will be placed just in the top left corner.

An absolute position element is positioned relative to the first parent element that has a position other than static. If no such element is found, the containing block is html

Hope this helps. See here for more information about CSS positioning.

I currently work with canvas speech balloons. But because the balloon with the pointer is wrapped in a div, some links under it aren't click able anymore. I cant use extjs in this case. See basic example for my speech balloon tutorial requires HTML5

So I decided to collect all link coordinates from inside the balloons in an array.

var clickarray=[];
function getcoo(thatdiv){
         thatdiv.find(".link").each(function(){
                 var offset=$(this).offset();           
                 clickarray.unshift([(offset.left),
                                     (offset.top),
                                     (offset.left+$(this).width()),
                                     (offset.top+$(this).height()),
                                     ($(this).attr('name')),
                                     1]);
                                     });
         }

I call this function on each (new) balloon. It grabs the coordinates of the left/top and right/down corners of a link.class - additionally the name attribute for what to do if someone clicks in that coordinates and I loved to set a 1 which means that it wasn't clicked jet. And unshift this array to the clickarray. You could use push too.

To work with that array:

$("body").click(function(event){
          event.preventDefault();//if it is a a-tag
          var x=event.pageX;
          var y=event.pageY;
          var job="";
          for(var i in clickarray){
              if(x>=clickarray[i][0] && x<=clickarray[i][2] && y>=clickarray[i][1] && y<=clickarray[i][3] && clickarray[i][5]==1){
                 job=clickarray[i][4];
                 clickarray[i][5]=0;//set to allready clicked
                 break;
                }
             }
          if(job.length>0){   
             // --do some thing with the job --
            }
          });

This function proofs the coordinates of a body click event or whether it was already clicked and returns the name attribute. I think it is not necessary to go deeper, but you see it is not that complicate. Hope in was enlish...

I'm adding this answer because I didn’t see it here in full. I was able to do this using elementFromPoint. So basically:

  • attach a click to the div you want to be clicked through
  • hide it
  • determine what element the pointer is on
  • fire the click on the element there.
var range-selector= $("")
    .css("position", "absolute").addClass("range-selector")
    .appendTo("")
    .click(function(e) {
        _range-selector.hide();

        $(document.elementFromPoint(e.clientX,e.clientY)).trigger("click");
    });

In my case the overlaying div is absolutely positioned—I am not sure if this makes a difference. This works on IE8/9, Safari Chrome and Firefox at least.

I needed to do this and decided to take this route:

$('.overlay').click(function(e){
    var left = $(window).scrollLeft();
    var top = $(window).scrollTop();

    //hide the overlay for now so the document can find the underlying elements
    $(this).css('display','none');
    //use the current scroll position to deduct from the click position
    $(document.elementFromPoint(e.pageX-left, e.pageY-top)).click();
    //show the overlay again
    $(this).css('display','block');
});

Click through a DIV to underlying element works different in browsers. Opera needs manual event forwarding, Firefox and Chrome understand CSS pointer-events:none; and IE doesn't need anything with transparent background; with e.g. background:white; opacity:0; filter:Alpha(opacity=0); IE needs forwarding like Opera.

See forwarding test at http://jsfiddle.net/vovcat/wf25Q/1/ and http://caniuse.com/pointer-events. Pointer-events CSS property has been moved from CSS3-UI to CSS4-UI.

You can place an AP overlay like...

#overlay {
  position: absolute;
  top: -79px;
  left: -60px;
  height: 80px;
  width: 380px;
  z-index: 2;
  background: url(fake.gif);
}
<div id="overlay"></div>

just put it over where you dont want ie cliked. Works in all.

  1. Hide overlaying the element
  2. Determine cursor coordinates
  3. Get element on those coordinates
  4. Trigger click on element
  5. Show overlaying element again
    $('#elementontop).click(function (e) {
        $('#elementontop).hide();
        $(document.elementFromPoint(e.clientX, e.clientY)).trigger("click");
        $('#elementontop').show();
    });

Another idea to try (situationally) would be to:

  1. Put the content you want in a div;
  2. Put the non-clicking overlay over the entire page with a z-index higher,
  3. make another cropped copy of the original div
  4. overlay and abs position the copy div in the same place as the original content you want to be clickable with an even higher z-index?

Any thoughts?

just wrap your a tag around all the html extract, for example

<a href="/categories/1">
    <img alt="test1" class="img-responsive" src="/assets/photo.jpg" />
        <div class="caption bg-orange">
            <h2>
                test1
            </h2>
        </div>
</a>

in my example my caption class has hover effects, that with pointer-events:none; you just will lose

wrapping the content will keep your hover effects and you can click in all the picture, div included, regards!

Also nice to know...
You can disable pointer-events in a parent element (probably transparent div) but have it still enabled for its child elements.
This is helpful if you work with multiple overlapping div layers, where you want to be able to click child elements, while having the parent layers not react on any mouse events at all. For this all parenting divs get pointer-events: none and its clickable children get pointer-events reenabled by pointer-events: auto

.parent {
    pointer-events:none;        
}
.child {
    pointer-events:auto;
}

<div class="some-container">
   <ul class="layer-0 parent">
     <li class="click-me child"></li>
     <li class="click-me child"></li>
   </ul>

   <ul class="layer-1 parent">
     <li class="click-me-also child"></li>
     <li class="click-me-also child"></li>
   </ul>
</div>

I think the event.stopPropagation(); should be mentioned here as well. Add this to the Click function of your button.

Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.