Hole in overlay with CSS

This is possible, to a degree.

Option 1: Covering element with semi-transparent border

body, html{
    height:100%;
    width:100%;
    padding:0;
    margin:0;
    background:blue;
}
#overlay{
    height:100%;
    width:100%;
    position:fixed;
    border:50px solid rgba(255,255,255,.3);
    box-sizing:border-box;
    top:0;
    left:0;
}
<div id='overlay'></div>

content content content contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent

Option 2: 3x3 grid with the central element fully transparent

body,
html {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
  position: fixed;
  background: blue;
}
#overlay {
  display: table;
  height: 100%;
  width: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
.row {
  display: table-row;
}
.cell {
  display: table-cell;
  opacity: 0.9;
  background: grey;
}
.row:nth-child(2) .cell:nth-child(2) {
  opacity: 0;
}
<div id='overlay'>
  <div class='row'>
    <div class='cell'></div>
    <div class='cell'></div>
    <div class='cell'></div>
  </div>
  <div class='row'>
    <div class='cell'>&nbsp;</div>
    <div class='cell'>&nbsp;</div>
    <div class='cell'>&nbsp;</div>
  </div>
  <div class='row'>
    <div class='cell'></div>
    <div class='cell'></div>
    <div class='cell'></div>
  </div>
</div>

content content content contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent
contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent
contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent contentcontent

Thank to CSS clip-path, it is now possible, even drilling any content of the overlay and its background-images / backdrop-filters and even pointer-events.

To do this, we need to define a path made of a first rectangle covering all the viewport, and then an inner shape that will represent our hole. Thanks to the even-odd fill-rule, only our inner shape will actually be part of the clipping-area.

That should have been easy to draw any shape with the path() <basic-shape>, but unfortunately, only Firefox supports it for clip-path, so we have to fallback using the polygon() function which means we have to define every points as vectors.

While it's still readable for a simple square hole:

.hole {
  position: fixed;
  width: 100vw;
  height: 100vh;
  top: 0px;
  left: 0px;
  --rect-size: 75px;
  clip-path: polygon( evenodd,
    /* outer rect */
    0 0, /* top - left */
    100% 0, /* top - right */
    100% 100%, /* bottom - right */
    0% 100%, /* bottom - left */
    0 0, /* and top - left again */
    /* do the same with inner rect */
    calc(50% - var(--rect-size) / 2) calc(50% - var(--rect-size) / 2),
    calc(50% + var(--rect-size) / 2) calc(50% - var(--rect-size) / 2),
    calc(50% + var(--rect-size) / 2) calc(50% + var(--rect-size) / 2),
    calc(50% - var(--rect-size) / 2) calc(50% + var(--rect-size) / 2),
    calc(50% - var(--rect-size) / 2) calc(50% - var(--rect-size) / 2)
  );
  /* can cut through all this */
  background-color: rgba(10, 161, 232, 0.3);
  background-image: url(https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png);
  background-size: 40px;
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  display: flex;
  justify-content: center;
}
.hole > p {
  align-self: center;
  font-size: 18px;
  font-weight: bold;
}
.hole-text {
  font-size: 100px;
}
body { color: black; }
<p>Lorem ipsum dolor sit amet, ocurreret tincidunt philosophia in sea, at pro postea ullamcorper. Mea ei aeque feugiat, cum ut utinam conceptam, in pro partem veritus molestiae. Omnis efficiantur an eum, te mel quot perpetua. Ad duo autem dolore, vocent
  lucilius te cum, ut duo quem singulis.</p>
<p>Has ex idque repudiandae, an mei munere philosophia. Sale molestie id eos, eam ne blandit adipisci. Ei eam ipsum dissentiunt. Ei vel accusam dolores efficiantur.</p>

<div class="hole">
  <p>There is an <span class="hole-text">HOLE</span> here</p>
</div>

Having all the points of a circle for instance would make for a far bigger rule, so if you don't need to cut through pointer-events, then the mask-image solution by Ed Hinchliffe should probably be preferred.

Anyway, here is a JS generator for a circle (the generated rule could still be hard-coded in a CSS file if needed).

function makeCircleHoleClipPathRule( radius ) {

  const inner_path = [];
  const circumference = Math.PI * radius;
  const step = Math.PI * 2 / circumference;
  // we are coming from top-left corner
  const start_step = circumference * (5 / 8);
  for( let i = start_step; i < circumference + start_step; i++ ) {
    const angle = step * i;
    const x = radius * Math.cos( angle );
    const y = radius * Math.sin( angle );
    const str = `calc( 50% + ${ x }px ) calc( 50% + ${ y }px )`;
    inner_path.push( str );
  }
  // avoid rounding issues
  inner_path.push( inner_path[ 0 ] );

  return `polygon( evenodd,
    /* outer rect */
    0 0,       /* top - left */
    100% 0,    /* top - right */
    100% 100%, /* bottom - right */
    0% 100%,   /* bottom - left */
    0 0,       /* and top - left again */
    ${ inner_path.join( "," ) }
   )`;

}

const hole_elem = document.querySelector( ".hole" );
// set the clip-path rule
hole_elem.style.clipPath = makeCircleHoleClipPathRule( 50 );
.hole {
  position: fixed;
  width: 100vw;
  height: 100vh;
  top: 0px;
  left: 0px;
  /* clip-path is set by JS */  
  
  background-color: rgba(10, 161, 232, 0.3);
  background-image: url(https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png);
  background-size: 40px;
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  display: flex;
  justify-content: center;
}
.hole > p {
  align-self: center;
  font-size: 18px;
  font-weight: bold;
}
.hole-text {
  font-size: 100px;
}
body { color: black; }
<p>Lorem ipsum dolor sit amet, ocurreret tincidunt philosophia in sea, at pro postea ullamcorper. Mea ei aeque feugiat, cum ut utinam conceptam, in pro partem veritus molestiae. Omnis efficiantur an eum, te mel quot perpetua. Ad duo autem dolore, vocent
  lucilius te cum, ut duo quem singulis.</p>
<p>Has ex idque repudiandae, an mei munere philosophia. Sale molestie id eos, eam ne blandit adipisci. Ei eam ipsum dissentiunt. Ei vel accusam dolores efficiantur.</p>

<div class="hole">
  <p>There is an <span class="hole-text">HOLE</span> here</p>
</div>

And for other shapes, I'll let the reader handle it ;-)


Yes, this effect is possible.

I would use the css box-shadow with a very large spread radius.

box-shadow: 0 0 0 9999px rgba(0, 0, 255, 0.2);

.hole {
  position: absolute;
  top: 20px;
  left: 20px;
  width: 200px;
  height: 150px;
  box-shadow: 0 0 0 9999px rgba(0, 0, 255, 0.2);
}
<p>Lorem ipsum dolor sit amet, ocurreret tincidunt philosophia in sea, at pro postea ullamcorper. Mea ei aeque feugiat, cum ut utinam conceptam, in pro partem veritus molestiae. Omnis efficiantur an eum, te mel quot perpetua. Ad duo autem dolore, vocent lucilius te cum, ut duo quem singulis.</p>
<p>Has ex idque repudiandae, an mei munere philosophia. Sale molestie id eos, eam ne blandit adipisci. Ei eam ipsum dissentiunt. Ei vel accusam dolores efficiantur.</p>

<div class="hole"></div>

Tags:

Css

Overlay