Assombrir tout l'écran sauf une zone fixe?

88

Je souhaite créer un didacticiel qui mènera l'utilisateur exactement là où cliquer. Je suis en train de couvrir tout l'écran avec <div>qui BAISSERA tous les éléments sauf une région spécifique qui est fixe width, height, topet left.

Le problème est que je ne trouve pas de moyen «d'annuler» celui du parent background-color(qui est également transparent).

Dans l'extrait ci-dessous, holeest le div qui est censé être sans aucun background-color, y compris son parent.

Cela peut-il être accompli du tout? Des idées?

#bg{
   background-color:gray;
   opacity:0.6;
   width:100%;
   height:100vh;
}
#hole{
   position:fixed;
   top:100px;
   left:100px;
   width:100px;
   height:100px;
}
<div id="bg">
    <div id="hole"></div>
</div>

Voici une maquette de ce que j'essaie d'accomplir:

entrez la description de l'image ici

Koby Douek
la source
13
Si vous créez une visite guidée / un didacticiel, vous pourriez être intéressé par l'une des bibliothèques js pour ce faire. Ils ont quelques fonctionnalités intéressantes et vous éviteront la peine d'écrire un tas d'effets css uniques. Consultez introjs.com ou linkedin.github.io/hopscotch .
octern
2
Ceci est juste une suggestion pour une lib: heelhook.github.io/chardin.js
ligne Thomas

Réponses:

125

Vous pouvez le faire avec un seul divet lui donner un box-shadow.

ÉDITER: comme @Nick Shvelidze l'a souligné, vous devriez envisager d'ajouterpointer-events: none

Valeur vmaxajoutée box-shadowcomme le suggère @Prinzhorn

div {
  position: fixed;
  width: 200px;
  height: 200px;
  top: 50px;
  left: 50px;
  /* for IE */
  box-shadow: 0 0 0 1000px rgba(0,0,0,.3);
  /* for real browsers */
  box-shadow: 0 0 0 100vmax rgba(0,0,0,.3);
  pointer-events: none;
}
<div></div>

VilleKoo
la source
28
Assurez-vous d'ajouter pointer-events: nonesi vous souhaitez que la zone en dessous soit cliquable.
Nick Shvelidze
4
1000px ne me semble pas suffisant - il semble qu'il y ait trop de cas où cela ne remplit pas l'écran, sinon une solution vraiment intelligente.
ESR
1
@EdmundReed, vous pouvez l'ajuster à vos besoins :)
VilleKoo
8
box-shadow: 0 0 0 100vmax rgba(0,0,0,.3);sera garanti pour couvrir tout l'écran
Prinzhorn
2
@VilleKoo, vous pouvez l'ajouter derrière la ligne 1000px et garder cela comme solution de repli
Prinzhorn
19

Vous pouvez créer un SVG qui est rempli d'un chemin avec le trou là où vous en avez besoin. Mais je suppose que vous devez trouver un moyen de gérer les clics, car tous seront ciblés sur le svg superposé. Je document.getElementFromPointpeux vous aider ici. mdn

philipp
la source
Je pense que le formulaire de commentaires de Google en utilisant svg pour atténuer la zone de repos.
Durga
3

Cela peut également être fait de la même manière que la réponse de @ VilleKoo, mais avec une bordure.

div {
    border-style: solid;
    border-color: rgba(0,0,0,.3);
    pointer-events: none;
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
    border-width: 40px 300px 50px 60px;
}
<div></div>

Dan
la source
2

Vous pouvez obtenir la même chose que dans la réponse de VilleKoo en utilisant CSSoutline propriété . Il a un excellent support de navigateur (et fonctionne également dans IE8 +). Les contours ont la même syntaxe que les bordures, mais contrairement aux bordures, ils ne prennent pas de place, ils sont dessinés au-dessus du contenu.

Aussi pour IE9 +, vous pouvez le remplacer 99999pxpar calc(100 * (1vh + 1vw - 1vmin)).

L'inconvénient de cette approche est qu'elle outlinen'est pas affectée par border-radius.

Démo:

div {
  position: fixed;
  width: 200px;
  height: 200px;
  top: 50px;
  left: 50px;
  /* IE8 */
  outline: 99999px solid rgba(0,0,0,.3);
  /* IE9+ */
  outline: calc(100 * (1vw + 1vh - 1vmin)) solid rgba(0,0,0,.3);
  /* for other browsers */
  outline: 100vmax solid rgba(0,0,0,.3);
  pointer-events: none;
}
<div></div>

Vadim Ovchinnikov
la source
0

Voici du code jQuery simple utilisant @VilleKoo css

var Dimmer = (function(){
  var el = $(".dimmer");
  
  return {
    showAt: function(x, y) {
      el
        .css({
          left: x,
          top: y,
        })
        .removeClass("hidden");
    },
    
    hide: function() {
      el.addClass("hidden");
    }
  }
}());


$(".btn-hide").click(function(){ Dimmer.hide(); });
$(".btn-show").click(function(){ Dimmer.showAt(50, 50); });
.dimmer {
  position: fixed;
  width: 200px;
  height: 200px;
  top: 50px;
  left: 50px;
  box-shadow: 0 0 0 1000px rgba(0,0,0,.3); /* for IE */
  box-shadow: 0 0 0 100vmax rgba(0,0,0,.3); /* for real browsers */
  pointer-events: none;
}

.hidden { display: none; }
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>

  <div>
    <input type="text">
    <select name="" id=""></select>
    <input type="checkbox">
  </div>
  <div>
    <input type="text">
    <select name="" id=""></select>
    <input type="checkbox">
  </div>
  <div>
    <input type="text">
    <select name="" id=""></select>
    <input type="checkbox">
  </div>
  <div>
    <input type="submit" disabled>
  </div>
  
  <input type="button" value="Hide" class="btn-hide">
  <input type="button" value="Show" class="btn-show">
  <div class="dimmer hidden"></div>
  <script src="https://code.jquery.com/jquery-2.2.4.js"></script>
</body>
</html>

Buksy
la source
0
#bg {
   background-color: gray;
   opacity: 0.6;
   position: absolute;
   top: 0;
   left: 0;
   width: 100%;
   height: 100%;
   z-index: 99998;
}
#hole {
   position: fixed;
   top: 100px;
   left: 100px;
   width: 100px;
   height: 100px;
   z-index: 99999;
}
zerdnelemo
la source