Use CSS to punch through a background

css transparent text see through background
background-clip css
css mask
css text mask animation
mix-blend-mode
css text background
css background image
css knockout

The question is very strange indeed, so let me explain with a snippet :

.container {
  width: 200px;
  height: 200px;
  background: rgba(200, 200, 200, .87);
}

.pin {
  position: absolute;
  left: 50px;
  top: 20px;
}

.overlay {
  position: absolute;
  left: 25px;
  top: 40px;
  background: grey;
  border: 1px solid white;
  padding: 12px;
  padding-top: 30px;
}

.overlay:before {
  content: '';
  position: absolute;
  border: 1px solid white;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  top: -30px;
  left: 10px;
}
<div class="container">
  <div class="pin">
    <svg width="24" height="36" viewBox="0 0 192 290" xmlns="http://www.w3.org/2000/svg">
      <path d="
        M11 138
        a 94 94 0 1 1 170 0
        l -85 150
        l -85 -150
      " fill="white" stroke="black" stroke-width="2" stroke-opacity="0.9" opacity="0.9" />
    </svg>
  </div>
  <div class="overlay">
    Content
  </div>
</div>

This is possible with an image mask using a radial-gradient (not supported by IE or Edge < 18)

.container {
  width: 200px;
  height: 200px;
  background: rgba(200, 200, 200, .87);
}

.pin {
  position: absolute;
  left: 50px;
  top: 20px;
}

.overlay {
  position: absolute;
  left: 25px;
  top: 40px;
  background: grey;
  border: 1px solid white;
  padding: 12px;
  padding-top: 30px;
}

.overlay:before {
  content: '';
  position: absolute;
  border: 1px solid white;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  top: 0;
  transform: translateY(-50%);
}

.masked-circle {
  -webkit-mask-image: radial-gradient(circle at 50% 0%, transparent 0, transparent 25px, black 25px);
}
<div class="container">
  <div class="pin">
    <svg width="24" height="36" viewBox="0 0 192 290" xmlns="http://www.w3.org/2000/svg">
      <path d="
        M11 138
        a 94 94 0 1 1 170 0
        l -85 150
        l -85 -150
      " fill="white" stroke="black" stroke-width="2" stroke-opacity="0.9" opacity="0.9" />
    </svg>
  </div>
  <div class="overlay masked-circle">
    Content
  </div>
</div>

CSS Techniques and Effects for Knockout Text, Dark foreground layer, with white text, set to "multiply" mix blend mode */ .text { color: white; background: rgb(59, 2, 6); mix-blend-mode: multiply  .clip-text-maybe { /* if we can clip, do it */ -webkit-text-fill-color: transparent; -webkit-background-clip: text; /* what will show through the text ~ or ~ what will be the background of that element */ background: whatever; /* fallback text color ~ or ~ the actual color of text, so it better work on the background */ color: red; }

Since the overlay belong to the element you can consider radial gradient and CSS variable in order to have something dynamic (without the border).

I removed the pin for simplicity but you can easily adjust its position to make it inside the circle or use it as background of overlay element:

.container {
  width: 200px;
  height: 120px;
  background: linear-gradient(red,yellow);
  display: inline-block;
  position: relative;
}

.overlay {
  --top: -3px;
  --left: 35px;
  --radius: 24px;
  position: absolute;
  left: 25px;
  top: 40px;
  background: radial-gradient(circle at var(--left) var(--top), transparent 0, transparent var(--radius), grey var(--radius));
  padding: 12px;
  padding-top: 30px;
}

.overlay:before {
  content: '';
  position: absolute;
  border: 1px solid white;
  width: calc(2*var(--radius));
  height: calc(2*var(--radius));
  border-radius: 50%;
  top: var(--top);
  left: var(--left);
  transform: translate(-50%, -50%);/*to keep the same origin*/
  background:url('data:image/svg+xml;utf8,<svg width="24" height="36" viewBox="0 0 192 290" xmlns="http://www.w3.org/2000/svg"><path d=" M11 138 a 94 94 0 1 1 170 0 l -85 150 l -85 -150" fill="white" stroke="black" stroke-width="2" stroke-opacity="0.9" opacity="0.9" /></svg>') center no-repeat;
}
<div class="container">
  <div class="overlay">
    Content
  </div>
</div>
<div class="container">
  <div class="overlay" style="--top:10px;--left:5px">
    Content
  </div>
</div>

<div class="container">
  <div class="overlay" style="--top:50px;--left:5px;--radius:30px;">
    Content
  </div>
</div>
<div class="container">
  <div class="overlay" style="--top:50px;--left:50px;--radius:40px;">
    Content
  </div>
</div>
<div class="container">
  <div class="overlay" style="--top:50px;--left:120px">
    Content
  </div>
</div>

How To Do Knockout Text, The beauty is that you can pair it with -webkit-text-fill-color: transparent; what will show through the text ~ or ~ what will be the background of that element  Transparency using RGBA. If you do not want to apply opacity to child elements, like in our example above, use RGBA color values. The following example sets the opacity for the background color and not the text:

You can give the ::before a grey box-shadow to fill the .overlay. The .overlay have overflow:hidden;so the shadow stays inside.

.container {
  width: 200px;
  height: 200px;
  background: rgba(200, 200, 200, .87);

}

.pin::before{
  content: '';
  position: absolute;
  border: 1px solid white;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  top: -10px;
  left: -12px;
}

.pin {
  position: absolute;
  left: 50px;
  top: 20px;
}

.overlay {
  position: absolute;
  left: 25px;
  top: 40px;
  border: 1px solid white;
  border-top:none;
  padding: 12px;
  padding-top: 30px;
  overflow:hidden;
  z-index:1
}

.overlay:before {
  content: '';
  position: absolute;
  border: 1px solid white;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  top: -30px;
  left: 12.3345px;
  background:transparent;
  box-shadow: 0 0 0 100px grey;
  z-index:-1;
}
<div class="container">
  <div class="overlay">
    Content
  </div>
  <div class="pin">
    <svg width="24" height="36" viewBox="0 0 192 290" xmlns="http://www.w3.org/2000/svg">
      <path d="
        M11 138
        a 94 94 0 1 1 170 0
        l -85 150
        l -85 -150
      " fill="white" stroke="black" stroke-width="2" stroke-opacity="0.9" opacity="0.9" />
    </svg>
  </div>
  
</div>

Use CSS to punch through a background The question is very , Use CSS to punch through a background The question is very strange indeed, so let me explain with a snippet : .container { width: 200px; height: 200px;  WebKit supports the cool background-clip CSS3 property, which you can use to do some pretty neat stuff. The first time we touched on it was the iPhone Slide-to-unlock idea where we set a gradient to animate through the background of the text. Then we touched on it again for the transparent borders idea.

CSS Pocket Reference, This can have the incorrect effect of punching “holes" in the background of the parent element. Opera 4 has a bug that shows up only when a background has  CSS background-image. The background-image property specifies an image to use as the background of an element.. By default, the image is repeated so it covers the entire element.

Smashing CSS: Professional Techniques for Modern Layout, If you want to make things a little more complex, you can set a background for the punch and use a nice thick border to separate it from the rest of the box, as in  As a new web designer, one very skill you'll need to master is using background images. Depending on the design, you may need to completely fill a CSS container with an image, or sometimes the image will just partially fill the container. In this post, we’ll show you three examples, using the CSS property background-size. Base CSS

Web Standards Creativity: Innovations in Web Design with XHTML, , Innovations in Web Design with XHTML, CSS, and DOM Scripting Andy Budd place a transparent image with the icon symbol “punched-out” over a square, or other shape with a flat-color CSS background, and you've got yourself an icon. You may use any of the following as values for background-size: a length, setting the width and height of the background image (in any valid CSS length units); e.g., background-size:20px 40px. a percentage, setting the width and height as a percentage of the parent element; e.g., background-size:50% 50%.

Comments
  • make the backgroud of the circle the same as the main background?
  • @TemaniAfif I thought I didn't have to state the obvious ... The pin is on a map, and I would like it to be transparent.
  • is this suitable stackoverflow.com/questions/8503636/… ?
  • @TemaniAfif No, if you increase the rectangle width on the JSFIddle, you will see it expends under the circle : I need it to expland at half the circle (Visually, half the circle should be in the content box, the other half should be outside the content box).
  • in this case, you can simply use the gradient as background instead of mask and you will have better support
  • On my screen, it renders very poorly (all blurry, like removing the background on a picture) and removes the white circle. is that normal ?
  • You're not really answering my question : my use-case is that I have a pin on a map (which is in a canvas, so I can't touch it). The content is placed at the exact same pixel the pin is on : with some CSS, I can adjust it, and I would like to circle around the pine with a transparent background. Like if the circle had punched through the content box. Although I have learned something, I can't use this, because it is a workaround not suited for me, and not a solution :/
  • @trichetriche in this case edit your question with the real use-case. I am answering based on your question and what you described, not based on the use-case I am not seeing.
  • @trichetriche the gradient is simply here to illustrate the transparency, It can be an image or a map, so the gradeint has nothing to do with the solution. And where you see any color here? the circle is transparent and punching through the background of the content element like you described
  • @trichetriche edit your question to include al these information then, There is nothing said that you will not use a solid color for your content, so I provided a solution based on this. And for the pin I simply made the effort to reduce the overal code (again based on the question not the use case). You can easily keep the pin outside. Check the update, I have added another method based on your requirement but again, they need to be reflected in your question. There is nothing generic in CSS and everything is workaround based on each situation.
  • @trichetriche all browsers: again something not said in your question. Well, I will leave this one, because I am pretty sure if I add another way you will then told me you want to support old IE, etc ;) . by the way a solution and workaround are the same and yes there is nothing generic in CSS. Each situation we will lead to a particular solution. Anyway, good luck, probably someone else will anwer with the generic solution you are looking for (as a side note, mask can be used with no webkit (developer.mozilla.org/en-US/docs/Web/CSS/mask-image), it can also be changed with SVG)
  • This is also a workaround : I don't need to match the color of the background, I need the circle to punch through the content box (meaning the background should be transparent).