Most animations move things or fade things. Clip-path does something different — it reveals things. Instead of an element appearing, it looks like it's being uncovered. That one difference makes it feel completely unlike a normal fade or slide.
It's also one of the most underused tools in CSS and Framer Motion, mostly because people assume it's complicated. It's not.
What clip-path actually does
Clip-path cuts a shape out of an element and only shows what's inside that shape. Animate the shape, and you animate what's visible — without touching opacity, position, or scale at all.
.reveal {
clip-path: inset(0 100% 0 0);
}
That single line hides everything except a 0-width sliver on the left. Animate the right value down to 0%, and the element appears to unfold from left to right — like a curtain opening, not a fade.
A simple reveal-on-scroll
This is where clip-path feels the most natural — content that reveals itself as it enters the screen, instead of just popping into place.
<motion.div
initial={{ clipPath: "inset(0 100% 0 0)" }}
whileInView={{ clipPath: "inset(0 0% 0 0)" }}
transition={{ duration: 0.6, ease: "easeOut" }}
>
Your content
</motion.div>
Nothing moves. Nothing fades. The content is just there one moment, uncovered a piece at a time. It reads as far more deliberate than a basic fade-in.
Circular reveals feel like a spotlight
Instead of a straight edge, use a circle. This is the effect you've probably seen on dark-mode toggles — a circle expanding from the click point until it covers the whole screen.
<motion.div
initial={{ clipPath: "circle(0% at 50% 50%)" }}
animate={{ clipPath: "circle(150% at 50% 50%)" }}
transition={{ duration: 0.5 }}
/>
Change the at values to match where the user actually clicked, and the animation feels like it's originating from their action instead of just playing on the screen.
Combine it with blur for something smoother
Clip-path on its own can look a little sharp — the edge is hard, clean, exact. Pair it with a touch of blur on that edge and the reveal feels softer, less mechanical.
<motion.div
initial={{ clipPath: "inset(0 100% 0 0)", filter: "blur(4px)" }}
whileInView={{ clipPath: "inset(0 0% 0 0)", filter: "blur(0px)" }}
transition={{ duration: 0.6 }}
>
Your content
</motion.div>
Same reveal, but it settles into place instead of snapping open.
Where it actually works well
Clip-path shines in specific spots — image reveals, section transitions, hero text on page load, theme toggles. It's not something you sprinkle everywhere. Used on the right element, it's the kind of detail people notice without knowing why. Used everywhere, it just gets tiring.
Fade and slide will always be the default, and that's fine — they're reliable. But clip-path is what you reach for when you want something to feel like it's being revealed, not just shown. That's a different feeling entirely, and it's a lot easier to build than most people think.