I am positioning an overlay on a webcam in my react app to show a user where to position their face. Here is my JSX:
<div className='webcam-container'>
<Webcam
ref={webcamRef}
screenshotFormat='image/jpeg'
screenshotQuality={1}
width={360}
/>
<div className='webcam-overlay'>
<div className='face-position-indicator' />
</div>
</div>
And here is my css:
.webcam-container {
position: relative;
width: 360px;
height: 270px;
}
.webcam-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
}
.face-position-indicator {
width: 150px;
height: 200px;
border: 2px solid #fff;
border-radius: 50%;
position: absolute;
top: 5%;
left: 10%;
z-index: 999;
}
It looks fine but I would like the background outside the <div className='face-position-indicator' />
to be shaded dark, so my question is how can I add a shading only to the div
with a class of webcam-overlay
but not the inner div
with a class of face-position-indicator
?
Here's what I've tried so far:
.webcam-overlay {
...
background-color: rgba(0, 0, 0, 0.9);
}
.face-position-indicator {
...
background-color: rgba(0, 0, 0, 0.1);
}
and:
.webcam-overlay {
...
background-color: rgba(0, 0, 0, 0.9);
}
.face-position-indicator {
...
background-color: transparent;
}
However both these attempts just give a dark shading to all the elements.
Interestingly if I do:
.webcam-overlay {
...
background-color: rgba(0, 0, 0, 0.1);
}
.face-position-indicator {
...
background-color: rgba(0, 0, 0, 0.9);
}
I get a light background on the outer div and a dark background on the inner div. But I can't achieve the opposite effect which is what I need.
Am I missing something? Is there some kind of css trick I need to apply? Chat GPT suggested adding a pseudo-element to my webcam-overlay
but this also just made everything dark.
EDIT: A more complicated but more flexible way to do this with SVG masks. I will say that I am not certain this is the best way to do this, though, but it definitely works.
.container{
position: relative;
width: 300px;
height: 300px;
}
.overlay{
position: absolute;
top: 0;
height: 100%;
width: 100%;
}
<div class="container">
<img src="https://images.unsplash.com/photo-1611915387288-fd8d2f5f928b?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8Mnx8fGVufDB8fHx8&w=1000&q=80" height="100%" width="100%">
<div class="overlay">
<svg height="100%" width="100%" viewBox="0 0 100 100">
<defs>
<mask id="mask" x="0" y="0" width="100%" height="100%">
<rect width="100%" height="100%" fill="rgb(255, 255, 255)"></rect>
<circle cx="25" cy="35" r="20"></circle>
</mask>
</defs>
<rect width="100%" height="100%" mask="url(#mask)" fill="rgba(0, 0, 0, .5)" ></rect>
</svg>
</div>
</div>
END EDIT
You can use an inset box-shadow with partial transparency:
.container{
position: relative;
width: 300px;
height: 300px;
}
.overlay{
position: absolute;
top: 0;
height: 100%;
width: 100%;
box-shadow: 0px 0px 0px 80px rgba(0, 0, 0, 0.5) inset;
}
<div class="container">
<img src="https://images.unsplash.com/photo-1611915387288-fd8d2f5f928b?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8Mnx8fGVufDB8fHx8&w=1000&q=80" height="100%" width="100%">
<div class="overlay">
</div>
</div>