Clipping and masks
Every element on the page is a rectangle. border-radius rounds the corners, but it cannot turn it into a star or an arrow. Clipping (clip-path) leaves visible only the part of the element inside a given shape, and a mask (mask-image) controls transparency using an image or a gradient.
clip-path: a circle
The circle() function cuts out a circle. The first number is the radius, the center goes after at:
<style>
img { clip-path: circle(40% at 50% 50%); }
</style>
<img src="/media/photo-200x200.jpg" alt="Photo" width="200" height="200">Everything outside the circle is invisible and does not catch mouse clicks, but the element takes the same space as before — a 200 by 200 square.
clip-path shapes
| Function | Shape | Example |
|---|---|---|
circle() | a circle | circle(50%) |
ellipse() | an ellipse: two radii | ellipse(50% 30%) |
inset() | a rectangle inset from the edges | inset(10px 20px round 12px) |
polygon() | a polygon through points | polygon(50% 0, 100% 100%, 0 100%) |
In polygon() each point is a pair of "x y" coordinates from the top left corner. Three points give a triangle, more give any shape:
<style>
.shape { width: 120px; height: 120px; display: inline-block; margin: 4px; background: tomato; }
.triangle { clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.arrow { clip-path: polygon(0 30%, 60% 30%, 60% 0, 100% 50%, 60% 100%, 60% 70%, 0 70%); }
.rounded { clip-path: inset(15px round 20px); }
</style>
<div class="shape triangle"></div>
<div class="shape arrow"></div>
<div class="shape rounded"></div>Animating the shape
clip-path can be animated if both shapes use the same function and the same number of points. Hover over the photo:
<style>
img { clip-path: circle(30%); transition: clip-path 0.5s; }
img:hover { clip-path: circle(75%); }
</style>
<img src="/media/photo-400x250.jpg" alt="Photo" width="400" height="250">The circle opens up to the whole picture — a popular effect for galleries.
mask-image: a smooth fade
A mask does not cut sharply, it sets transparency: where the mask is opaque, the element is visible, where it is transparent, the element disappears. The color of the mask does not matter, only its transparency does. A gradient from black to transparent dissolves the bottom of a block:
<style>
.fade {
max-width: 320px;
height: 90px;
overflow: hidden;
mask-image: linear-gradient(black 40%, transparent);
}
</style>
<p class="fade">The flat white is said to come from cafés in Australia and New Zealand in the eighties: baristas poured a thin, velvety layer of milk over a double espresso. The drink caught on and spread to coffee shops all over the world.</p>The text melts away towards the bottom — a way to show there is more to read. A mask can also be an image: mask-image: url(star.svg).
shape-outside: wrapping around a shape
The shape-outside property sets the shape that text flows around. It works only on a floated element — with float from the lesson "Floats". To make the picture itself round too, the same clip-path is added:
<style>
img {
float: left;
shape-outside: circle(50%);
clip-path: circle(50%);
margin-right: 12px;
}
p { max-width: 420px; margin: 0; }
</style>
<p><img src="/media/photo-200x200.jpg" alt="Photo" width="120" height="120">The lines of text bend around the round picture, not around its square frame. Near the top and bottom of the circle the lines start further left, and near the middle further right. The layout looks like a magazine page rather than a row of rectangles.</p>Common mistake
shape-outside without float does nothing: text flows only around floated elements. In the example below the property is set, but the picture sits in the line like an ordinary word, and the text does not wrap around it:
<style>
img { shape-outside: circle(50%); clip-path: circle(50%); }
</style>
<p><img src="/media/photo-200x200.jpg" alt="Photo" width="80" height="80">Without float the text does not wrap around the picture.</p>Add float: left — and the lines will settle around the circle.