web-dev-qa-db-fra.com

Cliquez sur div pour les éléments sous-jacents

J'ai un div qui a background:transparent, avec border. Sous cette div, j'ai plus d'éléments.

Actuellement, je peux cliquer sur les éléments sous-jacents lorsque je clique en dehors de la superposition div. Cependant, je ne parviens pas à cliquer sur les éléments sous-jacents lorsque je clique directement sur la superposition div.

Je veux pouvoir cliquer sur cette div pour pouvoir cliquer sur les éléments sous-jacents.

My Problem

1463
Ryan

Oui, vous POUVEZ faire ceci.

En utilisant pointer-events: none avec les instructions conditionnelles CSS pour IE11 (ne fonctionne pas dans IE10 ou une version antérieure), vous pouvez obtenir une solution compatible entre plusieurs navigateurs pour résoudre ce problème.

En utilisant AlphaImageLoader, vous pouvez même insérer .PNG/.GIFs transparent dans la superposition div et faire en sorte que les clics se propagent dans les éléments situés en dessous.

CSS:

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

IE11 conditionnel:

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

Voici un page d'exemple de base avec tout le code.

2429

Aussi agréable à savoir ...
Vous pouvez désactiver les événements de pointeur dans un élément parent (probablement une div transparente), mais l'activer pour ses éléments enfants.
Ceci est utile si vous travaillez avec plusieurs calques div qui se chevauchent, où vous voulez pouvoir cliquer sur des éléments enfants, tout en laissant les calques parents ne réagir à aucun événement de souris. Pour cela, tous les divs parents obtiennent pointer-events: none et ses enfants cliquables obtiennent des événements de pointeur réactivés par 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>
250
Allisone

Permettre à l'utilisateur de cliquer sur un div de l'élément sous-jacent dépend du navigateur. Tous les navigateurs modernes, y compris Firefox, Chrome, Safari et Opera, comprennent pointer-events:none .

Pour IE, cela dépend du fond. Si l'arrière-plan est transparent, le clic se déroule sans que vous ayez à faire quoi que ce soit. Par contre, pour quelque chose comme background:white; opacity:0; filter:Alpha(opacity=0);, IE nécessite un transfert d'événement manuel.

Voir n test JSFiddle et événements de pointeur CanIUse .

40
Vladimir Prodan

J'ajoute cette réponse parce que je ne l'ai pas vue ici dans son intégralité. J'ai pu faire cela en utilisant elementFromPoint. Donc en gros:

  • attachez un clic à la div par laquelle vous voulez être cliqué
  • cache le
  • déterminer sur quel élément se trouve le pointeur
  • déclenche le clic sur l'élément à cet endroit.
var range-selector= $("")
    .css("position", "absolute").addClass("range-selector")
    .appendTo("")
    .click(function(e) {
        _range-selector.hide();

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

Dans mon cas, la division superposée est parfaitement positionnée - je ne suis pas sûre que cela fasse une différence. Cela fonctionne sur IE8/9, Safari Chrome et Firefox au moins.

18
Tim
  1. Masquer en superposant l'élément
  2. Déterminer les coordonnées du curseur
  3. Obtenir un élément sur ces coordonnées
  4. Déclencheur cliquer sur l'élément
  5. Afficher à nouveau l'élément superposé
 
 $ ('# elementontop) .click (fonction (e) {
 $ (' # elementontop) .hide (); 
 $ (document.elementFromPoint (e.clientX, e.clientY)). trigger ("clic"); 
 $ ('# elementontop'). show (); 
}); 
 
12
wcloister

J'avais besoin de faire cela et j'ai décidé de suivre cette voie:

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

Je travaille actuellement avec des ballons en toile. Mais parce que la bulle avec le pointeur est enveloppée dans une div, certains liens en dessous ne sont plus cliquables. Je ne peux pas utiliser extjs dans ce cas. Voir l'exemple de base pour mon tutoriel sur les bulles de parole requiert HTML5

J'ai donc décidé de collecter toutes les coordonnées des liens à l'intérieur des bulles d'un tableau.

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

J'appelle cette fonction sur chaque (nouveau) ballon. Il saisit les coordonnées des coins gauche/haut et droit/bas d'un link.class - ainsi que l'attribut name pour savoir quoi faire si quelqu'un clique sur ces coordonnées et que j'aime définir un 1, ce qui signifie qu'il n'a pas été cliqué. . Et décaler ce tableau à la clickarray. Vous pouvez aussi utiliser Push.

Pour travailler avec ce tableau:

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

Cette fonction vérifie les coordonnées d'un événement de clic dans le corps ou s'il a déjà été cliqué et renvoie l'attribut name. Je pense qu'il n'est pas nécessaire d'aller plus loin, mais vous voyez que ce n'est pas si compliqué. L'espoir en était illuminé ...

6
B.F.

Une autre idée à essayer (au cas par cas) serait de:

  1. Mettez le contenu que vous voulez dans une div;
  2. Placez la superposition sans clic sur toute la page avec un index z supérieur,
  3. faire une autre copie recadrée de l'original div
  4. superposition et abs positionnent la copie div au même endroit que le contenu original sur lequel vous voulez cliquer avec un index z encore plus élevé?

Des pensées?

4
Adam

ça ne marche pas comme ça. La solution consiste à vérifier manuellement les coordonnées du clic de la souris par rapport à la zone occupée par chaque élément.

la zone occupée par un élément peut être trouvée trouvée en 1. obtenant l'emplacement de l'élément par rapport au coin supérieur gauche de la page, et 2. la largeur et la hauteur. une bibliothèque comme jQuery rend cela assez simple, bien que cela puisse être fait en clair js. l'ajout d'un gestionnaire d'événements pour mousemove sur l'objet document fournira des mises à jour continues de la position de la souris en haut et à gauche de la page. Décider si la souris survole un objet donné consiste à vérifier si la position de la souris est entre les bords gauche, droit, haut et bas d'un élément.

4
lincolnk

Non, vous ne pouvez pas cliquer sur un élément. Vous pouvez obtenir les coordonnées du clic et essayer de déterminer quel élément se trouvait sous l'élément cliqué, mais cela est vraiment fastidieux pour les navigateurs n'ayant pas document.elementFromPoint. Ensuite, vous devez encore émuler l'action par défaut de cliquer, ce qui n'est pas nécessairement trivial selon les éléments que vous avez en dessous.

Étant donné que vous avez une zone de fenêtre entièrement transparente, vous ferez probablement mieux de la mettre en place comme éléments de bordure séparés autour de l'extérieur, en laissant la zone centrale dégagée pour vous permettre de cliquer simplement.

4
bobince

Enroulez simplement la balise a autour de tous les extraits HTML, par exemple

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

dans mon exemple, ma classe de légende a des effets de survol, qui avec pointeur-événements: aucun; vous allez simplement perdre

envelopper le contenu conservera vos effets de survol et vous pourrez cliquer sur l’ensemble de l’image, div incluse, salutations!

2
Alexis

Je pense que vous pouvez envisager de changer votre marge bénéficiaire. Si je ne me trompe pas, vous souhaitez placer un calque invisible au-dessus du document et votre balise invisible peut précéder l'image de votre document (est-ce correct?).

Au lieu de cela, je propose que vous placiez l'invisible juste après l'image du document, mais en changeant la position en absolu.

Notez que vous avez besoin d'un élément parent pour avoir position: relative et vous pourrez alors utiliser cette idée. Sinon, votre couche absolue sera placée dans le coin supérieur gauche.

Un élément de position absolue est positionné par rapport au premier élément parent qui a une position autre que statique. Si aucun élément de ce type n'est trouvé, le bloc conteneur est html

J'espère que cela t'aides. Voir ici pour plus d'informations sur le positionnement CSS.

2
julianm

Vous pouvez placer une superposition AP comme ...

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

il suffit de le mettre là où vous ne voulez pas, c'est-à-dire cliké. Fonctionne en tout.

1
eric

Je pense que la event.stopPropagation(); devrait également être mentionnée. Ajoutez ceci à la fonction Click de votre bouton.

Empêche l'événement de remonter dans l'arborescence DOM, empêchant ainsi les gestionnaires parents d'être avertis de l'événement.

0
kenny

Ce n'est pas une réponse précise à la question, mais cela peut aider à trouver une solution de contournement.

J'avais une image que je cachais au chargement de la page et que je vis en attendant un appel AJAX, puis qui se cachait à nouveau ...

J'ai trouvé le seul moyen d'afficher mon image lors du chargement de la page, puis de la faire disparaître et de pouvoir cliquer sur les éléments où se trouvait l'image avant de la cacher: placer l'image dans un DIV, faire une taille de 10x10 pixels ou plus petite assez pour l'empêcher de causer un problème, puis cacher le div contenant. Cela permettait à l'image de déborder de la div lorsqu'elle était visible et lorsque la div était masquée, seule la zone des divs était affectée par l'impossibilité de cliquer sur les objets situés en dessous et non par la taille de l'image contenue et affichée.

J'ai essayé toutes les méthodes pour masquer l'image, y compris l'affichage CSS = none/block, opacity = 0, masquant l'image avec hidden = true. Ils ont tous masqué mon image, mais la zone dans laquelle elle était affichée agissait comme s'il y avait une couverture sur le contenu situé en dessous de sorte que les clics, etc., n'agissent pas sur les objets sous-jacents. Une fois que l'image était dans une petite DIV et que je cachais la petite DIV, toute la zone occupée par l'image était claire et seule la minuscule zone cachée sous la DIV que je cachais était affectée, mais la taille de l'image était suffisamment petite (10 x 10 pixels). a été corrigé (en quelque sorte).

J'ai trouvé qu'il s'agissait d'une solution de contournement pour ce qui devrait être un problème simple, mais je n'ai trouvé aucun moyen de masquer l'objet dans son format natif sans conteneur. Mon objet était sous la forme de etc. Si quelqu'un a un meilleur moyen, s'il vous plaît faites le moi savoir.

0
David Crawford

Une méthode plus simple consisterait à intégrer l’image d’arrière-plan transparente à l’aide des données URI, comme suit:

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