9

I've read this great question already Transparent hollow or cut out circle but I want to draw more circles (let's say three).

So I tried using an extra element for the circle instead of a pseudo-element (so I can add more) and it works for one circle but not for more. The problem is that they are not transparent since the last one covers everything. Here is my attempt:

body{
  background-color:violet;
}
.shape{  
    height: 150px;
    width: 150px;
    position:relative;
    overflow:hidden;
}
.hole{
    position:absolute;
    border-radius:100%;
    width:30px; height:30px;
    color:red;
    box-shadow: 0px 0px 0px 2000px black;
}
.hole:nth-child(1) {
    left:25px; top:25px; 
}
.hole:nth-child(2) {
    left:65px; top:25px; 
}
.hole:nth-child(3) {
    left:55px; top:65px; 
}
<div class="shape">
  <div class="hole">1</div>
  <div class="hole">2</div>
  <div class="hole">3</div>
</div>
Community
  • 1
  • 1
Theodore K.
  • 5,058
  • 4
  • 30
  • 46
  • 1
    This technique cannot work for multiple circles, you will have to resort to SVG. The box-shadows of each circle are visible above each other, this makes it look as if there was only one circle remaining. Interesting question btw! – connexo Dec 06 '16 at 10:10
  • 1
    You can probably get some ideas from https://css-tricks.com/clipping-masking-css/ – Patrick Dec 06 '16 at 10:35
  • This might be of help friend, http://stackoverflow.com/questions/20360750/multiple-perfect-circles-in-css#20361533 – gutierrezalex Jan 24 '17 at 22:55

4 Answers4

12

Just use an svg. Black part of mask is removed from the element it is applied to and white is kept:

html, body {
  height: 100%;
  margin: 0;
  background: linear-gradient(to top, red, blue);
}

svg {
  display: block;
  width: 150px;
}
<svg viewBox="0 0 150 150">
  <mask id="circles" maskUnits="objectBoundingBox">
    <rect x="0" y="0" width="100%" height="100%" fill="white" />
    <circle cx="40" cy="40" r="15" fill="black" />
    <circle cx="80" cy="40" r="15" fill="black" />
    <circle cx="70" cy="80" r="15" fill="black" />
  </mask>
  
  <rect x="0" y="0" width="100%" height="100%" fill="green" style="mask: url(#circles)" />
</svg>
Qwertiy
  • 19,681
  • 15
  • 61
  • 128
  • 2
    Just simple and awesome..this perfect answer for "Multiple transparent circles" – Sayed Rafeeq Dec 06 '16 at 12:06
  • 1
    I like the simplicity of this code, upvoted and accepted already. However, a small explenation (of how mask works in this case) would be helpful for future readers. – Theodore K. Dec 06 '16 at 12:26
  • 1
    @TheodoreK., it seems very simple: black part of mask is removed and white is kept. – Qwertiy Dec 06 '16 at 12:32
  • 1
    @Qwertiy, I get that but it gets lots inside the snippet code. Put this small description inside your answer, on top, just to help future readers to catch that at first sight, that this is an answer using an svg mask. Anyway, it's your choise, thanks for your help. – Theodore K. Dec 06 '16 at 12:39
6

If you really want to make this with CSS and if you aren't afraid of multiple box-shadows, you could do this BUT you must be aware that this is hard coded and the values for box-shadow must be updated when the cirlces change position, size or number.

Here is an example of the approach you can use, the values for box shadow should be "optimized" :

body {
  background: url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-size:cover;
}
.shape {
  height: 150px;
  width: 150px;
  position: relative;
  overflow: hidden;
}
.hole {
  position: absolute;
  border-radius: 100%;
  width: 30px;
  height: 30px;
  color: red;
}
.hole:nth-child(1) {
  left: 25px;
  top: 25px;
  box-shadow: -38px -33px 0px 55px black, 9px 14px 0px 0px black;
}
.hole:nth-child(2) {
  left: 65px;
  top: 25px;
  box-shadow: 76px -63px 0px 100px black, -7px 6px 0px 0px black;
}
.hole:nth-child(3) {
  left: 55px;
  top: 65px;
  box-shadow: -3px 91px 0px 100px black;
}
<div class="shape">
  <div class="hole">1</div>
  <div class="hole">2</div>
  <div class="hole">3</div>
</div>

Other than that, I would clearly recomend using SVG either with masking/clipping or with a path as shown in the answer you linked to. Here is an example with several cut out transparent circles using the path element with the arc command :

body{background: url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-size:cover;}
svg{
  display:block;
  width:70%;
  height:auto;
  margin:0 auto;
}
path{
  transition:fill .5s;
  fill:#E3DFD2;
}
<svg viewbox="-10 -1 30 15">
  <path d="M-10 -1 H30 V15 H-10z 
           M 5 5 m -5, 0 
           a 5,5 0 1,0 10,0 
           a 5,5 0 1,0 -10,0
           M-3 10 m -2, 0
           a 2,2 0 1 ,0 4,0
           a 2,2 0 1 ,0 -4,0
           M15 8 m -2, 0
           a 2,2 0 1 ,0 4,0
           a 2,2 0 1 ,0 -4,0
           M-5 5 m -2, 0
           a 2,2 0 1 ,0 4,0
           a 2,2 0 1 ,0 -4,0"/>
</svg>

The above code is fomarted so each circle in the path element is "drawn" with :

M cx cy m -r, 0
a r,r 0 1,0 (r * 2),0
a r,r 0 1,0 -(r * 2),0

The center of the circle is cx, cy and r is its radius. See this answer for an explanation.
The first line (M-10 -1 H30 V15 H-10z) is made to make the surounding rectangle and each cirlce "cuts it out".

The advantage of this approach is that it works for all browsers that support inline svg. Even those who don't support masking or clipping.

To understand how this works, you should take a look at :

CL.
  • 173,858
  • 17
  • 217
  • 259
web-tiki
  • 99,765
  • 32
  • 217
  • 249
0

You can use the rgba color values specifying opacity instead of using a single color for your box-shadow to have the desired effect.

Try box-shadow: 0px 0px 0px 2000px rgba(0, 0, 0 , 0.1);

nashcheez
  • 5,067
  • 1
  • 27
  • 53
  • Thanks for the effort but that's not the desired effect, I'm trying to draw transparent circles in a black square. – Theodore K. Dec 06 '16 at 10:06
  • This does not address the core problem. Probably it doesn't even *understand* the core problem. – connexo Dec 06 '16 at 10:13
  • This answer does understand the core problem. But the fact here is it is difficult to attain what the OP is asking for, so this answers offers an alternative (to which the questioner disagreed to which is fine :)) – nashcheez Dec 06 '16 at 10:24
0

<!DOCTYPE html>
<html>
<head>
<style>
.shape{  
    height: 150px;
    width: 150px;
    position:relative;
    overflow:hidden;
 background-color:#333333;
}
.hole{
    position:absolute;
    border-radius:20px;
    width:20px; 
 height:20px;
    color:red;
    background-color:white;
 opacity:0.6; /* for transparency levels change between 0=invisible and 1=opaque */
 text-align:center;
}
.hole:nth-child(1) {
    left:25px; top:25px; 
}
.hole:nth-child(2) {
    left:65px; top:25px; 
}
.hole:nth-child(3) {
    left:55px; top:65px; 
}
</style>
</head>
<body>
 <div class="shape">
   <div class="hole">1</div>
   <div class="hole">2</div>
   <div class="hole">3</div>
 </div>
</body>
</html>
Sahana
  • 577
  • 8
  • 11
  • Opacity is having levels. You can change it between 0 and 1 as per your needs. you can add color of your choice. With same color for the circle and the background, you will not be able to see the circle. Even circle is 100% transparent also you will not be able to see the circle. Only if you have semi transparent with different color than background for the circle only you will be able to see it. – Sahana Dec 06 '16 at 10:37
  • Sorry for trying to give solution without understanding the problem :( – Sahana Dec 06 '16 at 10:47
  • 4
    Answers should almost **never** contain *only code*. – connexo Dec 06 '16 at 11:51