web-dev-qa-db-fra.com

"Superposition" HTML permettant aux clics de tomber sur des éléments situés derrière

J'essaie de superposer un élément au-dessus d'une page Web (pour dessiner des graphiques arbitraires) et je suis arrivé au point où je peux l'empiler à l'intérieur d'un élément au-dessus de tout, mais cela empêche l'utilisateur de cliquer sur des liens/boutons/etc. Existe-t-il un moyen de laisser son contenu flotter au-dessus de tout (il est semi-transparent, afin que vous puissiez toujours voir ce qu'il y a derrière) et que l'utilisateur interagisse avec le calque situé en dessous?

J'ai trouvé beaucoup d'informations sur le modèle d'événement DOM, mais aucune ne résout le problème selon lequel les boutons et autres contrôles "natifs" ne semblent jamais obtenir les clics.

161
Steven Schlansker

Un bidon idiot que j'ai fait était de régler la hauteur de l'élément à zéro mais de déborder: visible; combinant ceci avec des événements de pointeur: aucun; semble couvrir toutes les bases.

.overlay {
    height:0px;
    overflow:visible;
    pointer-events:none;
    background:none !important;
}
114
Flatliner DOA

Ajoutez pointer-events: none; à la superposition.


Réponse originale: Ma suggestion serait que vous puissiez capturer l'événement click avec la superposition, masquer la superposition, puis ré-activer l'événement click, puis afficher à nouveau la superposition. Je ne sais pas si vous obtiendrez un effet de scintillement.

[Mise à jour] Ce problème et ma solution sont apparus dans ce message: " transmission d'événements de souris par le biais de calques ". Je sais que c'est probablement un peu tard pour le PO, mais si quelqu'un avait ce problème à l'avenir, je pensais l'inclure.

42
Russell Leggett

Pour l’enregistrement, une autre approche pourrait consister à transformer le calque cliquable en superposition: vous le rendez semi-transparent et placez ensuite l’image "superposition" derrière le (légèrement contre-intuitif, l’image "superposition" pourrait alors être opaque). En fonction de ce que vous essayez de faire, vous pourrez peut-être obtenir exactement le même effet visuel (d’une image et d’un calque cliquable superposé de manière semi-transparente), tout en évitant les problèmes de "est en fait en arrière plan).

6
Nick F

Au cas où quelqu'un rencontrerait le même problème, la seule solution que je pouvais trouver et qui me satisferait serait que la toile recouvre tout, puis d'augmenter l'indice Z de tous les éléments cliquables. Vous ne pouvez pas dessiner sur eux, mais au moins ils sont cliquables ...

5
Steven Schlansker

Mon équipe a rencontré ce problème et l'a très bien résolu.

  • ajoutez une classe "passthrough" ou quelque chose de différent à chaque élément sur lequel vous souhaitez cliquer et qui se trouve sous la superposition.
  • pour chaque élément ".passthrough", ajoutez un div et positionnez-le exactement au-dessus de son parent. ajoutez la classe "élément-superposition" à cette nouvelle div.
  • Le fichier css ".element-overlay" doit avoir un indice z élevé (au-dessus de la superposition de la page) et les éléments doivent être transparents.

Cela devrait résoudre votre problème, car les événements du ".element-overlay" devraient se transformer en ".passthrough". Si vous avez toujours des problèmes (nous n'en avons pas vu jusqu'à présent), vous pouvez jouer avec la reliure.

Ceci est une amélioration de la solution de @ jvenema.

La bonne chose à ce sujet est que

  • vous ne passez pas par TOUS les événements à TOUS les éléments. Juste ceux que vous voulez. (résolu l'argument de @ jvenema)
  • Tous les événements fonctionneront correctement. (survol par exemple).

Si vous avez des problèmes s'il vous plaît faites le moi savoir afin que je puisse élaborer.

4
guy mograbi

Vous pouvez utiliser une superposition avec une opacité définie pour que les boutons/ancres à l'arrière restent visibles, mais une fois que vous avez cette superposition sur un élément, vous ne pouvez pas cliquer dessus.

3
yoda

Généralement, ce n'est pas une bonne idée. Dans votre scénario, si vous aviez de mauvaises intentions, vous pourriez tout cacher sous votre "superposition". Ensuite, lorsqu'un utilisateur clique sur un lien qu'il pense devoir amener sur bankofamerica.com, il déclenche à la place le lien caché qui le dirige vers myevilsite.com.

Cela dit, la propagation d'événements fonctionne, et si cela se trouve dans une application, ce n'est pas grave. Le code suivant est un exemple. En cliquant sur la zone bleue, une alerte s’affiche, même si l’alerte est définie sur la zone rouge. Notez que la zone orange NE FONCTIONNE PAS, car l'événement se propage à travers les éléments PARENT. Votre superposition doit donc être à l'intérieur quel que soit l'élément sur lequel vous observez les clics. Dans votre scénario, vous n’avez peut-être pas de chance.

<html>
<head>
</head>
<body>
    <div id="outer" style="position:absolute;height:50px;width:60px;z-index:1;background-color:red;top:5px;left:5px;" onclick="alert('outer')"> 
        <div id="nested" style="position:absolute;height:50px;width:60px;z-index:2;background-color:blue;top:15px;left:15px;">
        </div>
    </div>
    <div id="separate" style="position:absolute;height:50px;width:60px;z-index:3;background-color:orange;top:25px;left:25px;">
    </div>
</body>
</html>
2
jvenema

Que diriez-vous de cela pour IE ?:

onmousedown: Cacher tous les éléments qui pourraient superposer l'événement. Parce que display: none visibilité: hidden ne fonctionne pas vraiment, poussez le div superposé de l'écran pour un nombre fixe de pixels. Après un délai Poussez le div superposé avec le même nombre de pixels.

onmouseup: En attendant, c’est l’événement que vous aimez déclencher.

     //script
     var allclickthrough=[];         
     function hidedivover(){
              if(allclickthrough.length==0){
                allclickthrough=getElementsByClassName(document.body,"clickthrough");// if so .parentNode
                }
              for(var i=0;i<allclickthrough.length;i++){
                 allclickthrough[i].style.left=parseInt(allclickthrough[i].style.left)+2000+"px";
                 }
              setTimeout(function(){showdivover()},1000);   
              }
    function showdivover(){
             for(var i=0;i<allclickthrough.length;i++){
                allclickthrough[i].style.left=parseInt(allclickthrough[i].style.left)-2000+"px";
                }
             }       
    //html
    <span onmouseup="Dreck_he_got_me()">Click me if you can.</span>
    <div  onmousedown="hidedivover()" style="position:absolute" class="clickthrough">You'll don't get through!</div>
0
B.F.