Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

css: exclude (hide) specific area from element

Tags:

html

css

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: enter image description here

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!

like image 885
ch1p_ Avatar asked Nov 27 '25 05:11

ch1p_


1 Answers

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...

like image 72
sudo rm -rf slash Avatar answered Nov 28 '25 20:11

sudo rm -rf slash



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!