Clip Path

Reveal and mask elements with animated CSS clip-path.

Clip path masks portions of an element using CSS clip-path, letting you reveal or hide content by animating the shape of the visible region. Use it for circle reveals, diagonal wipes, polygon morphs, and any geometry-driven entrance or exit effect.

Basic Usage

Pass 'clip-path' (or clipPath) inside from and/or to. Both endpoints must use the same shape function for smooth interpolation.

typescript
import { Motion } from "@motion.page/sdk";

Motion("reveal", "#hero", {
  from: { "clip-path": "circle(0% at 50% 50%)" },
  to:   { "clip-path": "circle(75% at 50% 50%)" },
  duration: 1,
  ease: "power2.out",
}).onPageLoad();

Supported Shapes

ShapeExample
circle'circle(50% at 50% 50%)'
ellipse'ellipse(60% 30% at 50% 50%)'
inset'inset(10px 20px round 8px)'
polygon'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)'
rect'rect(10px 90px 90px 10px)'
xywh'xywh(10% 10% 80% 80%)'

Property Name

Both forms are equivalent — use whichever fits your style:

typescript
// kebab-case (quoted)
from: { "clip-path": "circle(0% at 50% 50%)" }

// camelCase
from: { clipPath: "circle(0% at 50% 50%)" }

The SDK also automatically writes -webkit-clip-path alongside clip-path for Safari compatibility — you don’t need to set it manually.

Interpolation Rules

For smooth animation between two states:

  • Same shape on both endscircle → circle, polygon → polygon. Mixing shapes (e.g. circle → inset) causes a hard swap at progress ≥ 0.5.
  • Polygon vertex counts must matchpolygon(0% 0%, 100% 0%, 100% 100%) (3 vertices) cannot smoothly tween to a 4-vertex polygon.
  • Units are preserved — mix of % and px values within a shape is fine, but the same unit should be used for each corresponding coordinate between from and to.

From-Only / To-Only

Like all SDK properties, you can supply just one endpoint and the SDK reads the other from the element’s computed CSS:

typescript
// from-only — element has clip-path set in CSS, animate into it
Motion("reveal", ".card", {
  from: { clipPath: "inset(100% 0% 0% 0%)" },
  duration: 0.7,
  ease: "power3.out",
}).onScroll({ scrub: false, toggleActions: "play none none none" });

// to-only — animate away from the element's natural clip-path
Motion("hide", ".card", {
  to: { clipPath: "inset(0% 0% 100% 0%)" },
  duration: 0.5,
  ease: "power2.in",
}).onClick({ each: true });

Shape Examples

Circle Reveal

Expand a circle from the center — the classic reveal effect.

typescript
Motion("circle-reveal", "#hero", {
  from: { "clip-path": "circle(0% at 50% 50%)" },
  to:   { "clip-path": "circle(75% at 50% 50%)" },
  duration: 1,
  ease: "power2.out",
}).onPageLoad();

Ellipse

Expand an ellipse from a custom focal point.

typescript
Motion("ellipse-in", ".banner", {
  from: { clipPath: "ellipse(0% 0% at 50% 50%)" },
  to:   { clipPath: "ellipse(80% 60% at 50% 50%)" },
  duration: 0.9,
  ease: "power3.out",
}).onPageLoad();

Inset

inset clips all four edges simultaneously. Shrink from all sides to reveal content.

typescript
Motion("inset-reveal", ".image", {
  from: { "clip-path": "inset(50% round 8px)" },
  to:   { "clip-path": "inset(0% round 8px)" },
  duration: 0.8,
  ease: "expo.out",
}).onScroll({ scrub: false, toggleActions: "play none none none" });

Polygon Diagonal Wipe (Hover)

Morph a polygon on hover for a sharp diagonal wipe effect.

typescript
Motion("wipe", ".card", {
  from: { clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)" },
  to:   { clipPath: "polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%)" },
  duration: 0.4,
  ease: "power2.inOut",
}).onHover({ each: true, onLeave: "reverse" });

rect

rect specifies the clipping rectangle using top, right, bottom, and left edge values.

typescript
Motion("rect-reveal", ".panel", {
  from: { "clip-path": "rect(50% 50% 50% 50%)" },
  to:   { "clip-path": "rect(0% 100% 100% 0%)" },
  duration: 0.7,
  ease: "power2.out",
}).onPageLoad();

xywh

xywh defines the clip region by x offset, y offset, width, and height — useful when you know the dimensions of the visible area you want.

typescript
Motion("xywh-reveal", ".feature", {
  from: { clipPath: "xywh(50% 50% 0% 0%)" },
  to:   { clipPath: "xywh(0% 0% 100% 100%)" },
  duration: 0.8,
  ease: "power3.out",
}).onPageLoad();

Common Patterns

Circle Reveal on Page Load

The most common use case — reveal a hero section or image with an expanding circle.

typescript
import { Motion } from "@motion.page/sdk";

Motion("hero-reveal", "#hero", {
  from: { "clip-path": "circle(0% at 50% 50%)" },
  to:   { "clip-path": "circle(150% at 50% 50%)" },
  duration: 1.2,
  ease: "power2.out",
}).onPageLoad();

Using 150% guarantees the circle covers the full element regardless of its aspect ratio.

Diagonal Wipe on Hover

Reveal a card overlay with a triangle wipe driven by hover.

typescript
Motion("card-wipe", ".card .overlay", {
  from: { clipPath: "polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%)" },
  to:   { clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)" },
  duration: 0.5,
  ease: "power2.out",
}).onHover({ each: true, onLeave: "reverse" });

Polygon Morph (Shape Shifting)

Smoothly morph between two polygon shapes — vertex count must be identical.

typescript
Motion("morph", ".blob", {
  from: { clipPath: "polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)" },
  to:   { clipPath: "polygon(25% 0%, 75% 25%, 100% 75%, 25% 100%)" },
  duration: 2,
  ease: "power1.inOut",
  repeat: { times: -1, yoyo: true },
}).onPageLoad();

Both shapes here use 4 vertices — the morph is smooth because the vertex counts match.

  • Opacity — fade elements in and out
  • Scale — grow or shrink elements
  • SVG — animate SVG paths and stroke effects