0

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.

sgt_pepper85
  • 421
  • 4
  • 14

2 Answers2

1

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>
Jake
  • 862
  • 6
  • 10
  • Interesting. Is it possible to apply this to a curved shape that is positioned off-center though? – sgt_pepper85 Mar 21 '23 at 19:17
  • Hmmm maybe, maybe not, depends on the exact needs. Can you update your question with a more detailed description of what you need? – Jake Mar 21 '23 at 19:37
  • My `
    ` is an oval shape positioned towards the top left of `
    `. This is the element I would like to have light while the rest of `
    ` appears shaded
    – sgt_pepper85 Mar 21 '23 at 19:41
  • Added a flexible SVG solution, mostly stolen from [this post](https://stackoverflow.com/questions/61991739/why-is-my-svg-mask-partially-transparent) – Jake Mar 21 '23 at 19:52
  • Works great! I just changed `` to `` to suit my specific needs. Thanks so much – sgt_pepper85 Mar 21 '23 at 21:43
1

You can try like below:

.container{
  position: relative;
  width: 300px;
  height: 300px;
  overflow: hidden; /** don't forget this */
}

.container:before{
  content:"";
  position: absolute;
  width: 100px;
  aspect-ratio: 1;
  top: 50px;
  left:50px;
  border-radius: 10px;
  box-shadow: 0 0 0 100vmax #0009; /* a big box-shadow will do the trick*/ 
}

img {
  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"">
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415