除了固定区域,整个屏幕都变暗了吗?

我想创建一个教程,将导致用户确切地点击。我试图用一个 <div>覆盖整个屏幕,它会调暗所有的元素,除了 特定区域是在一个固定的 widthheighttopleft

问题是,我无法找到一种方法来“取消”父代的 background-color(它也是透明的)。

在下面的剪辑中,hole是假定没有任何 background-color的 div,包括它的父类。

这能完成吗? 有什么办法吗?

#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>

下面是我正在努力实现的目标的一个模型图像:

enter image description here

12630 次浏览

You can create an SVG which is filled with a path that has the hole where you need it to. But I guess than you need to find a way to handle clicks, since all of them will be targeted to the overlaid svg. I thing document.getElementFromPoint can help you here. mdn

You could do it with just one div and give it a box-shadow.

EDIT: as @Nick Shvelidze pointed out, you should consider adding pointer-events: none

Added vmax value for box-shadow as @Prinzhorn suggested

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>

This can also be done similarly to @VilleKoo's answer, but with a border.

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>

Here is simple jQuery code using @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>

#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;
}

You can achieve the same as in VilleKoo's answer using CSS outline property. It has excellent browser support (and works also in IE8+). Outlines have the same syntax as borders, but unlike border they don't take up space, they are drawn above the content.

Also for IE9+ you can replace 99999px with calc(100 * (1vh + 1vw - 1vmin)).

Disadvantage of this approach is that outline is not affected by border-radius.

Demo:

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>