With CSS3 clip-path option I can easily clip element so that only specified area will be visible. It's cool, but is there a way to exclude an area so that everything except specified path will be visible?
Here is an example of what I want to do. I need to cut a circle out:

Placing a circle over is not an option because I need the underlying background to be visible.
AFAIK one way to do it is by using canvas, but is it possible with pure CSS?
Thanks!
Sure it's possible. Use clip-path! Imagine your div is piece of paper and clip-path is a pair of scissors. If you wanted to cut out a circle in the middle, you'd cut around the edges, along a line into the middle, around a circle, and back to the edge along the same line.
I hacked together a python script that outputs the CSS. Apologies for the style...
import math
# radius in percent of width
radius = 0.25
# xy pos in percent
xPos = 0.5
yPos = 0.5
# number of points around the circle
# size of css is approx proportional to this
smooth = 50
# from here, just go around the outline of the shape
x = []
y = []
x.append(0)
y.append(0)
x.append(0)
y.append(1)
x.append(xPos - radius)
y.append(1)
x.append(xPos - radius)
y.append(yPos)
angleZero = math.pi
increment = 2 * math.pi / smooth
numDigits = 3
for k in range(0, smooth):
angle = angleZero - k * increment
x.append( round( xPos + radius * math.cos(angle), numDigits ) )
y.append( round( yPos - radius * math.sin(angle), numDigits ) )
x.append(xPos - radius)
y.append(yPos)
x.append(xPos - radius)
y.append(1)
x.append(1)
y.append(1)
x.append(1)
y.append(0)
cssValue = "polygon(";
for k in range(0, len(x) - 1):
cssValue += str( abs(x[k]*100) ) + "% " + str( abs(y[k]*100) ) + "%, "
cssValue += str( abs(x[len(x) - 1]*100) ) + "% " + str(abs( y[len(x) - 1]*100) ) + "%);"
property = "clip-path: "
spaces = " "
print(".excludeCircle{");
print(spaces + "-webkit-"+property + cssValue)
print(spaces + property + cssValue)
print("}")
Here's what it looks like:
.excludeCircle{
-webkit-clip-path: polygon(0% 0%, 0% 100%, 25.0% 100%, 25.0% 50.0%, 25.0% 50.0%, 25.2% 46.9%, 25.8% 43.8%, 26.8% 40.8%, 28.1% 38.0%, 29.8% 35.3%, 31.8% 32.9%, 34.1% 30.7%, 36.6% 28.9%, 39.4% 27.4%, 42.3% 26.2%, 45.3% 25.4%, 48.4% 25.0%, 51.6% 25.0%, 54.7% 25.4%, 57.7% 26.2%, 60.6% 27.4%, 63.4% 28.9%, 65.9% 30.7%, 68.2% 32.9%, 70.2% 35.3%, 71.9% 38.0%, 73.2% 40.8%, 74.2% 43.8%, 74.8% 46.9%, 75.0% 50.0%, 74.8% 53.1%, 74.2% 56.2%, 73.2% 59.2%, 71.9% 62.0%, 70.2% 64.7%, 68.2% 67.1%, 65.9% 69.3%, 63.4% 71.1%, 60.6% 72.6%, 57.7% 73.8%, 54.7% 74.6%, 51.6% 75.0%, 48.4% 75.0%, 45.3% 74.6%, 42.3% 73.8%, 39.4% 72.6%, 36.6% 71.1%, 34.1% 69.3%, 31.8% 67.1%, 29.8% 64.7%, 28.1% 62.0%, 26.8% 59.2%, 25.8% 56.2%, 25.2% 53.1%, 25.0% 50.0%, 25.0% 100%, 100% 100%, 100% 0%);
clip-path: polygon(0% 0%, 0% 100%, 25.0% 100%, 25.0% 50.0%, 25.0% 50.0%, 25.2% 46.9%, 25.8% 43.8%, 26.8% 40.8%, 28.1% 38.0%, 29.8% 35.3%, 31.8% 32.9%, 34.1% 30.7%, 36.6% 28.9%, 39.4% 27.4%, 42.3% 26.2%, 45.3% 25.4%, 48.4% 25.0%, 51.6% 25.0%, 54.7% 25.4%, 57.7% 26.2%, 60.6% 27.4%, 63.4% 28.9%, 65.9% 30.7%, 68.2% 32.9%, 70.2% 35.3%, 71.9% 38.0%, 73.2% 40.8%, 74.2% 43.8%, 74.8% 46.9%, 75.0% 50.0%, 74.8% 53.1%, 74.2% 56.2%, 73.2% 59.2%, 71.9% 62.0%, 70.2% 64.7%, 68.2% 67.1%, 65.9% 69.3%, 63.4% 71.1%, 60.6% 72.6%, 57.7% 73.8%, 54.7% 74.6%, 51.6% 75.0%, 48.4% 75.0%, 45.3% 74.6%, 42.3% 73.8%, 39.4% 72.6%, 36.6% 71.1%, 34.1% 69.3%, 31.8% 67.1%, 29.8% 64.7%, 28.1% 62.0%, 26.8% 59.2%, 25.8% 56.2%, 25.2% 53.1%, 25.0% 50.0%, 25.0% 100%, 100% 100%, 100% 0%);
}
img{
width: 300px;
height: 200px;
}
body{
background-color: green;
}
<div style="position: absolute;">
This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background. This is text in the background.
</div>
<img src="https://i.sstatic.net/l2ETg.png" class="excludeCircle"/>
Edit: One issue with this method is that it really makes an oval. You could fix this by using px in the circle (if you know the min-size of the element) or by having an x radius and a y radius (if you know the relative sizes). If you know nothing, you'll need some js...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With