Haga clic en div para ver los elementos subyacentes.

1593

Tengo un divque tiene background:transparent, junto con border. Debajo de estodiv , tengo más elementos.

Actualmente, puedo hacer clic en los elementos subyacentes cuando hago clic fuera de la superposición div. Sin embargo, no puedo hacer clic en los elementos subyacentes cuando hago clic directamente en la superposición div.

Quiero poder hacer clic en esto divpara poder hacer clic en los elementos subyacentes.

Mi problema

Ryan
fuente

Respuestas:

2616

Sí, PUEDES hacer esto.

Utilizando pointer-events: nonejunto con las declaraciones condicionales CSS para IE11 (no funciona en IE10 o inferior), puede obtener una solución compatible con varios navegadores para este problema.

Utilizando AlphaImageLoader, incluso puede poner .PNG/.GIFs transparentes en la superposición divy hacer que los clics fluyan a los elementos debajo.

CSS:

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

IE11 condicional:

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

Aquí hay una página de ejemplo básica con todo el código.

LawrenceKSRealEstate
fuente
77
¿Qué pasa si estoy usando transiciones o estados de desplazamiento en ese div?
Manticore
2
@Manticore Respuesta corta: No puedes. En este caso, la respuesta proporcionada no funciona.
Niels Abildgaard
10
IE11 es totalmente compatible con eventos de puntero. Esto significa que todos los navegadores modernos lo admiten. Esta es una solución viable a fines de 2014. caniuse.com/#search=pointer-events
Judah Gabriel Himango
Como señaló @Andy, esto rompe el desplazamiento. Abrí un número separado para ver si hay una solución para este stackoverflow.com/questions/41592349/…
Oliver Joseph Ash
1
@Manticore Descubrí que puede sobrescribir "eventos de puntero: ninguno"; para el elemento anidado, para que pueda escribir algo omitido por clic con algo que obtiene el clic y más, para las partes sobrescritas puede usar efectos y clic
Luca C.
292

También es bueno saberlo ...
Puede deshabilitar los eventos de puntero en un elemento primario (probablemente div transparente) pero aún así habilitarlo para sus elementos secundarios.
Esto es útil si trabaja con múltiples capas div superpuestas, donde desea poder hacer clic en elementos secundarios, mientras que las capas primarias no reaccionan ante ningún evento del mouse.

Para esto, se obtienen todos los divs de crianza pointer-events: noney sus hijos en los que se puede hacer clic se vuelven a habilitar eventos de puntero porpointer-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>
Todo es uno
fuente
44
Perfecto, ¡esto es justo lo que necesitaba!
RobbyReindeer
1
super útil, gracias
SpaceBear
43

Permitir que el usuario haga clic en un divelemento subyacente depende del navegador. Todos los navegadores modernos, incluidos Firefox, Chrome, Safari y Opera, entienden pointer-events:none.

Para IE, depende del fondo. Si el fondo es transparente, el clic funciona sin que tenga que hacer nada. Por otro lado, para algo así background:white; opacity:0; filter:Alpha(opacity=0);, IE necesita reenvío manual de eventos.

Vea una prueba JSFiddle y eventos de puntero CanIUse .

Vladimir Prodan
fuente
20

Estoy agregando esta respuesta porque no la vi aquí por completo. Pude hacer esto usando elementFromPoint. Así que básicamente:

  • adjunte un clic al div en el que desea que se haga clic
  • esconderlo
  • determinar en qué elemento está el puntero
  • dispare el clic sobre el elemento allí.
var range-selector= $("")
    .css("position", "absolute").addClass("range-selector")
    .appendTo("")
    .click(function(e) {
        _range-selector.hide();

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

En mi caso, el div superpuesto está en una posición absoluta; no estoy seguro de si esto hace la diferencia. Esto funciona en IE8 / 9, Safari Chrome y Firefox al menos.

Tim
fuente
12
  1. Ocultar superposición del elemento
  2. Determinar las coordenadas del cursor
  3. Obtener elemento en esas coordenadas
  4. Activar clic en elemento
  5. Mostrar elemento superpuesto nuevamente
$('#elementontop').click(e => {
    $('#elementontop').hide();
    $(document.elementFromPoint(e.clientX, e.clientY)).trigger("click");
    $('#elementontop').show();
});
wcloister
fuente
¿Has olvidado cerrar los apóstrofes? Tal vez $('#elementontop)debería ser $('#elementontop')?
johannchopin
10

Necesitaba hacer esto y decidí tomar esta ruta:

$('.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');
});
Matthew Grima
fuente
6

Actualmente trabajo con globos de discurso de lona. Pero debido a que el globo con el puntero está envuelto en un div, algunos enlaces debajo ya no pueden hacer clic. No puedo usar extjs en este caso. Ver ejemplo básico para mi tutorial de globo de discurso requiere HTML5

Así que decidí recopilar todas las coordenadas del enlace desde el interior de los globos en una matriz.

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]);
                                     });
         }

Llamo a esta función en cada (nuevo) globo. Toma las coordenadas de las esquinas izquierda / superior y derecha / abajo de un enlace. Clase: además, el atributo de nombre de qué hacer si alguien hace clic en esas coordenadas y me encantó establecer un 1, lo que significa que no se hizo clic en chorro . Y desplace esta matriz a la matriz de clics. Podrías usar push también.

Para trabajar con esa matriz:

$("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 --
            }
          });

Esta función prueba las coordenadas de un evento de clic en el cuerpo o si ya se hizo clic y devuelve el atributo de nombre. Creo que no es necesario profundizar, pero ya ves que no es tan complicado. Hope in was enlish ...

BF
fuente
4

No funciona de esa manera. la solución consiste en verificar manualmente las coordenadas del clic del mouse contra el área ocupada por cada elemento.

el área ocupada por un elemento se puede encontrar encontrando 1. obteniendo la ubicación del elemento con respecto a la parte superior izquierda de la página, y 2. el ancho y la altura. una biblioteca como jQuery lo hace bastante simple, aunque se puede hacer en js simple. agregar un controlador de eventos para mousemoveel documentobjeto proporcionará actualizaciones continuas de la posición del mouse desde la parte superior e izquierda de la página. decidir si el mouse está sobre cualquier objeto dado consiste en verificar si la posición del mouse está entre los bordes izquierdo, derecho, superior e inferior de un elemento.

Lincoln
fuente
2
Como se mencionó anteriormente, puede lograr esto usando CSS {pointer-events: none;} en su contenedor transparente.
Empereol
4

No, no puedes hacer clic a través de un elemento. Puede obtener las coordenadas del clic e intentar determinar qué elemento estaba debajo del elemento en el que se hizo clic, pero esto es realmente tedioso para los navegadores que no lo tienen document.elementFromPoint. Luego, aún debe emular la acción predeterminada de hacer clic, que no es necesariamente trivial dependiendo de los elementos que tenga debajo.

Como tiene un área de ventana totalmente transparente, probablemente sea mejor implementarlo como elementos de borde separados alrededor del exterior, dejando el área central libre de obstrucciones para que realmente pueda hacer clic directamente.

bobince
fuente
4

Otra idea para intentar (situacionalmente) sería:

  1. Ponga el contenido que desea en un div;
  2. Coloque la superposición sin clic en toda la página con un índice z más alto,
  3. hacer otra copia recortada del div original
  4. superposición y abs colocan el div de copia en el mismo lugar que el contenido original en el que desea que se pueda hacer clic con un índice z aún mayor.

¿Alguna idea?

Adán
fuente
2

Creo que puedes considerar cambiar tu marcado. Si no me equivoco, le gustaría poner una capa invisible sobre el documento y su marcado invisible puede estar precediendo a la imagen de su documento (¿es esto correcto?).

En cambio, le propongo que coloque lo invisible justo después de la imagen del documento pero que cambie la posición a absoluta.

Tenga en cuenta que necesita un elemento padre para tener position: relative y luego podrá usar esta idea. De lo contrario, su capa absoluta se colocará justo en la esquina superior izquierda.

Un elemento de posición absoluta se coloca en relación con el primer elemento padre que tiene una posición distinta de estática. Si no se encuentra dicho elemento, el bloque contenedor es html

Espero que esto ayude. Consulte aquí para obtener más información sobre el posicionamiento CSS.

julianm
fuente
2

Simplemente envuelva la aetiqueta alrededor de todo el extracto HTML, por ejemplo

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

en mi ejemplo, mi clase de subtítulos tiene efectos de desplazamiento, que con eventos de puntero: ninguno; solo perderás

envolver el contenido mantendrá sus efectos de desplazamiento y puede hacer clic en toda la imagen, div incluido, saludos!

Alexis
fuente
¡buen punto! gracias
Mr.Vertigo
1

Puede colocar una superposición AP como ...

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

simplemente colóquelo donde no quiera, es decir, haga clic. Funciona en todos.

eric
fuente
1

Una forma más fácil sería alinear la imagen de fondo transparente utilizando URI de datos de la siguiente manera:

.click-through {
    pointer-events: none;
    background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);
}
MathuSum Mut
fuente
0

Creo que también event.stopPropagation();debería mencionarse aquí. Agregue esto a la función Click de su botón.

Impide que el evento forme burbujas en el árbol DOM, evitando que los controladores principales sean notificados del evento.

kenny
fuente
0

Esta no es una respuesta precisa para la pregunta, pero puede ayudarlo a encontrar una solución.

Tenía una imagen que estaba ocultando en la carga de la página y que se mostraba cuando esperaba una llamada AJAX y luego la ocultaba de nuevo ...

Encontré la única forma de mostrar mi imagen al cargar la página, luego hacerla desaparecer y poder hacer clic en las cosas donde estaba ubicada la imagen antes de ocultarla era poner la imagen en un DIV, hacer que el tamaño del DIV sea de 10x10 píxeles o pequeño suficiente para evitar que cause un problema y luego ocultar el div que contiene. Esto permitió que la imagen desbordara el div mientras estaba visible y cuando el div estaba oculto, solo el área de divs se veía afectada por la incapacidad de hacer clic en los objetos debajo y no por el tamaño completo de la imagen que el DIV contenía y mostraba.

Intenté todos los métodos para ocultar la imagen, incluida CSS display = none / block, opacity = 0, ocultando la imagen con hidden = true. Todos ellos hicieron que mi imagen se ocultara, pero el área donde se mostraba actuaba como si hubiera una cubierta sobre las cosas debajo, por lo que los clics y demás no actuarían sobre los objetos subyacentes. Una vez que la imagen estaba dentro de un pequeño DIV y escondí el pequeño DIV, todo el área ocupada por la imagen estaba clara y solo el área pequeña debajo del DIV que escondí se vio afectada, pero como lo hice lo suficientemente pequeño (10x10 píxeles), el problema fue corregido (más o menos).

Encontré que esto es una solución sucia para lo que debería ser un problema simple, pero no pude encontrar ninguna forma de ocultar el objeto en su formato nativo sin un contenedor. Mi objeto era en forma de etc. Si alguien tiene una mejor manera, hágamelo saber.

David Crawford
fuente