← Back to CSS Course | Chapter 8: Animations & Effects | Lesson 15 of 22

CSS Image Shapes

A photo doesn't have to stay a rectangle — border-radius and clip-path can crop an image into a circle, an ellipse, a triangle, or a custom polygon entirely in CSS, with no image-editing software involved.
Syntax
css
img {
  shape-outside: circle();
  float: left;
  border-radius: 50%;
}

Circles and Ellipses with border-radius

Setting border-radius: 50% on a square image crops it into a perfect circle, while applying it to a non-square image produces an ellipse instead — this is the simplest shape technique and works in every modern browser with no vendor prefixes.

Note:
  • Accepted values:
  • border-radius: 50% — circle on a square box, ellipse otherwise
  • border-radius: <length> — fixed rounding
  • border-radius: A / B — horizontal / vertical radii
  • aspect-ratio: 1 — keeps the box square

Example: Circles and Ellipses with border-radius

css
<style>
img {
  border-radius: 50%;
}
</style>
<img src="https://placehold.co/100x100" alt="Cropped into a circle">

Introducing clip-path

clip-path defines an arbitrary visible region for an element using basic shape functions like circle(), ellipse(), polygon(), or inset() — anything outside the defined shape is simply clipped away, revealing the page background (or whatever sits behind it) underneath.

Note:
  • Accepted values:
  • clip-path: circle() — circular clip
  • clip-path: ellipse() — elliptical clip
  • clip-path: polygon() — any straight-edged shape
  • clip-path: inset() — rectangle, optionally rounded
  • clip-path: path() — clip with an SVG path string
  • clip-path: none — default, no clipping
  • inherit | initial | unset | revert — CSS-wide keywords accepted by every property

Example: Introducing clip-path

css
<style>
img {
  clip-path: circle(50%);
}
</style>
<img src="https://placehold.co/150x150" alt="Clipped, revealing what's behind it">

Polygon Shapes

clip-path: polygon(...) takes a list of x,y coordinate pairs defining a custom straight-edged shape — a triangle, a diamond, a hexagon, or an arrow — by connecting the listed points in order around the element's box.

Note:
  • Accepted values:
  • polygon(x y, x y, ...) — list of vertices, at least three
  • polygon(evenodd, ...) — fill rule (nonzero is default)
  • <percentage> — relative to the reference box
  • <length> — fixed offset

Example: Polygon Shapes

css
<style>
.triangle {
  width: 150px;
  height: 150px;
  background: teal;
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}
</style>
<div class="triangle"></div>

Animating Shape Changes

Because clip-path values can be transitioned, hovering an element can morph its clipped shape smoothly from one polygon to another (as long as both shapes have the same number of coordinate points), a technique impossible with border-radius alone.

Note:
  • Accepted values:
  • clip-path: polygon(...) — animatable when the point count matches
  • transition: clip-path 0.4s — animates the change
  • same number of points — required for smooth interpolation
  • clip-path: none — cannot be interpolated

Example: Animating Shape Changes

css
<style>
.shape {
  width: 150px;
  height: 150px;
  background: crimson;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
  transition: clip-path 0.3s;
}
.shape:hover {
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}
</style>
<div class="shape"></div>

border-radius vs clip-path

border-radius only rounds corners and can't produce anything besides rectangles-with-rounded-corners, circles, and ellipses, while clip-path can create arbitrary polygon and curve-based shapes — reach for clip-path whenever the desired shape isn't a simple rounded rectangle or ellipse.

Example: border-radius vs clip-path

css
<style>
.rounded {
  width: 100px;
  height: 100px;
  background: gray;
  border-radius: 20px;
}
.hexagon {
  width: 100px;
  height: 100px;
  background: gray;
  clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}
</style>
<div class="rounded"></div>
<div class="hexagon"></div>
Live Example
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Using clip-path and expecting the layout space to change, when it stays the same.
  2. Writing a polygon() with points in the wrong order, so the shape looks wrong.
  3. Using border-radius: 50% on a rectangle and getting an oval, when a circle needs a square.
Browser Support

Supported in all modern browsers: Chrome, Firefox, Safari, Edge and Opera.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.