How to Make an Inverse Transparent Circle in CSS

CSS 3 Shape: Inverse Circle or Cut Out Circle

Update: CSS3 Radial Background Gradient Option

(For those browsers supporting it--tested in FF and Chrome--IE10, Safari should work too).

One "problem" with my original answer is those situations where one does not have a solid background that they are working against. This update creates the same effect allowing for a transparent "gap" between the circle and it's inverse cutout.

See example fiddle.

CSS

.inversePair {
border: 1px solid black;
display: inline-block;
position: relative;
height: 100px;
text-align: center;
line-height: 100px;
vertical-align: middle;
}

#a {
width: 100px;
border-radius: 50px;
background: grey;
z-index: 1;
}

#b {
width: 200px;
/* need to play with margin/padding adjustment
based on your desired "gap" */
padding-left: 30px;
margin-left: -30px;
/* real borders */
border-left: none;
-webkit-border-top-right-radius: 20px;
-webkit-border-bottom-right-radius: 20px;
-moz-border-radius-topright: 20px;
-moz-border-radius-bottomright: 20px;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
/* the inverse circle "cut" */
background-image: -moz-radial-gradient(
-23px 50%, /* the -23px left position varies by your "gap" */
circle closest-corner, /* keep radius to half height */
transparent 0, /* transparent at center */
transparent 55px, /*transparent at edge of gap */
black 56px, /* start circle "border" */
grey 57px /* end circle border and begin color of rest of background */
);
background-image: -webkit-radial-gradient(-23px 50%, circle closest-corner, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 55px, black 56px, grey 57px);
background-image: -ms-radial-gradient(-23px 50%, circle closest-corner, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 55px, black 56px, grey 57px);
background-image: -o-radial-gradient(-23px 50%, circle closest-corner, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 55px, black 56px, grey 57px);
background-image: radial-gradient(-23px 50%, circle closest-corner, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 55px, black 56px, grey 57px);
}

Original Answer

Took more effort than I expected to get the z-indexing to work (this seems to ignore the negative z-index), however, this gives a nice clean look (tested in IE9, FF, Chrome):

HTML

<div id="a" class="inversePair">A</div>
<div id="b" class="inversePair">B</div>

CSS

.inversePair {
border: 1px solid black;
background: grey;
display: inline-block;
position: relative;
height: 100px;
text-align: center;
line-height: 100px;
vertical-align: middle;
}

#a {
width: 100px;
border-radius: 50px;
}

#a:before {
content:' ';
left: -6px;
top: -6px;
position: absolute;
z-index: -1;
width: 112px; /* 5px gap */
height: 112px;
border-radius: 56px;
background-color: white;
}

#b {
width: 200px;
z-index: -2;
padding-left: 50px;
margin-left: -55px;
overflow: hidden;
-webkit-border-top-right-radius: 20px;
-webkit-border-bottom-right-radius: 20px;
-moz-border-radius-topright: 20px;
-moz-border-radius-bottomright: 20px;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}

#b:before {
content:' ';
left: -58px;
top: -7px;
position: absolute;
width: 114px; /* 5px gap, 1px border */
height: 114px;
border-radius: 57px;
background-color: black;
}

Transparent hollow or cut out circle

You can achieve a transparent cut out circle with 2 different techniques :

1.SVG

The following examples use an inline svg. The first snippet uses the mask element to cut out the transparent circle and the second hollow circle is made with a path element. The circle is made with 2 arc commands :

With the mask element :

body{background:url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-size:cover;}
<svg viewbox="0 0 100 50" width="100%">
<defs>
<mask id="mask" x="0" y="0" width="80" height="30">
<rect x="5" y="5" width="90" height="40" fill="#fff"/>
<circle cx="50" cy="25" r="15" />
</mask>
</defs>
<rect x="0" y="0" width="100" height="50" mask="url(#mask)" fill-opacity="0.7"/>
</svg>

CSS 3 Shape: “Inverse Circle” or “Cut Out Circle”

You can use the following solution (original answer):

body {  padding: 10px;  background: url(http://www.dummyimage.com/12x16/ff0000/ffffff.png&text=X++) top left repeat;}.inversePair {  border: 1px solid black;  display: inline-block;  position: relative;  height: 100px;  text-align: center;  line-height: 100px;  vertical-align: middle;}#a {  width: 100px;  border-radius: 50px;  background: grey;  z-index: 1;}#b {  width: 200px;  /* need to play with margin/padding adjustment       based on your desired "gap" */  padding-right: 30px;  margin-right: -30px;  /* real borders */  border-right: none;  -webkit-border-top-left-radius: 20px;  -webkit-border-bottom-left-radius: 20px;  -moz-border-radius-topleft: 20px;  -moz-border-radius-bottomleft: 20px;  border-top-left-radius: 20px;  border-bottom-left-radius: 20px;  /* the inverse circle "cut" */  background-image: -moz-radial-gradient(calc(100% + 23px) 50%, /* the -23px left position varies by your "gap" */  circle closest-corner, /* keep radius to half height */  transparent 0, /* transparent at center */  transparent 55px, /*transparent at edge of gap */  black 56px, /* start circle "border" */  grey 57px/* end circle border and begin color of rest of background */  );  background-image: -webkit-radial-gradient(calc(100% + 23px) 50%, circle closest-corner, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 55px, black 56px, grey 57px);  background-image: -ms-radial-gradient(calc(100% + 23px) 50%, circle closest-corner, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 55px, black 56px, grey 57px);  background-image: -o-radial-gradient(calc(100% + 23px) 50%, circle closest-corner, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 55px, black 56px, grey 57px);  background-image: radial-gradient(calc(100% + 23px) 50%, circle closest-corner, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 55px, black 56px, grey 57px);}
<div id="b" class="inversePair">B</div><div id="a" class="inversePair">A</div>

Inverse oval in CSS

You can try something with pseudo-elements like :before . Other solution would be with SVG but i made an answer just with a :before element.

Add it to the inverseoval div and shape it and position it how you want.

Be careful to give it the same background-color as for the content.

.content {  height: 200px;  background: black;  padding-bottom: 50px;}
.inverseoval { height: 100px; background: red; position: relative; overflow: hidden;}
.inverseoval:before { position: absolute; top: -20px; left: 0; content: ""; height: 80px; width: 100%; transform: rotate(-2deg); background-color: black; border-bottom-left-radius: 100%; border-bottom-right-radius: 100%;}
<div class="content">
</div><div class="inverseoval"></div>

CSS box Inverse Circle and SlideShow

it will be easier for you to give your images a border radius (or a border radius for the slideshow container div) than to make a transparent image to show the slideshow through. http://jsfiddle.net/B9sLT/3/

    border-top-left-radius: 40px;
-moz-border-radius-topleft: 40px;
-webkit-border-top-left-radius: 40px;
border-bottom-left-radius: 40px;
-moz-border-radius-bottom-left: 40px;
-webkit-border-bottom-left-radius: 40px;

*updated fiddle to show you how it looks on the gradient background. the example image that you have linked is two layered images, which is easier for most people to create bc it does not use as much css.

CSS Invert colors in transparent svg element

One way of achieving the required result is close to the code given in the question.

The color of the text in the p element is inverted so that the part lying over the circle has the color cyan. The background of the element containing the p and svg (in this snippet's case, the body) has a background of white set so the mix-blend-mode on the text takes the difference of the color (which is now #00ffff = cyan) and white (#ffffff) to take us back to red (#ff0000).

As noted in comments, it's not possible to invert the SVG circle color as it has transparency so will always have that whatever RGB it has inverted so it's filled with a solid color.

body {
background: white;
height: 100vh;
}

.cursor {
position: absolute;
top: 0;
left: 0;
}

.cursor__inner {
fill: black;
}

p {
color: cyan;
color: red;
filter: invert(1);
mix-blend-mode: difference;
}
<body>
<svg class="cursor" width="64" height="64" viewBox="0 0 64 64">
<circle class="cursor__inner" cx="32" cy="32" r="32" />
</svg>
<p>Hello World!</p>
</body>


Related Topics



Leave a reply



Submit