Dim entire screen except a fixed area?
JavascriptJqueryHtmlCssJavascript Problem Overview
I want to create a tutorial which will lead the user exactly where to click. I'm trying to cover the entire screen with a <div>
which will dim all elements except a specific region which is in a fixed width
, height
, top
and left
.
The problem is, I cannot find a way to "cancel" the parent's background-color
(which is also transparent).
In the snipped below, hole
is the div that is supposed to be without any background-color
, including its parent's.
Can this be accomplished at all? Any ideas?
#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>
Here's a mockup image of what I'm trying to achieve:
Javascript Solutions
Solution 1 - Javascript
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>
Solution 2 - Javascript
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
Solution 3 - Javascript
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>
Solution 4 - Javascript
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>
Solution 5 - Javascript
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>
Solution 6 - Javascript
#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;
}