Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple transparent circles using only css (cutouts)

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>
like image 890
Theodore K. Avatar asked Dec 06 '16 09:12

Theodore K.


2 Answers

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>
like image 113
Qwertiy Avatar answered Nov 15 '22 23:11

Qwertiy


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 :

  • SVG in HTML (inline)
  • the path command
  • and specificaly the arc command
like image 38
web-tiki Avatar answered Nov 15 '22 23:11

web-tiki