skip to Main Content

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.

2

Answers


  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>
    Login or Signup to reply.
  2. 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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search