Smooth Follow Cursor
A spring-physics custom cursor with a deforming blob follower.
A custom cursor driven by spring physics: the center dot sticks to the fingertip while the outer ring converges behind it, stretching and deforming along the direction of travel according to cursor speed to produce a "soft-bodied" trailing tail.
Bring this into your project
Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.
npx webberui@latest add smooth-follow-cursor.enSmooth Follow Cursor is a React custom cursor component built with Tailwind CSS and Motion springs. Wrap a section with it and the native cursor inside is replaced by a center dot plus a trailing ring; pressing the mouse button shrinks the ring and enlarges the dot.
Playground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<SmoothFollowCursor/>
The complete example includes the preview layout and data. Install the component first, then paste this file into your project.
When to use
- Hero area of a portfolio or design studio homepage, where the cursor itself is part of the interaction feedback.
- Hero section of a product launch or event page, paired with large headings on a dark background.
- Browsing-oriented blocks such as interactive showcases or project walls with few form fields.
- Not a good fit: forms, text editors or dashboards that need precise clicking, where the native cursor works better. If you only want one button to feel magnetic, use Magnetic Button instead.
Installation
npx webberui@latest add https://webberui.com/r/smooth-follow-cursor.en.jsonOr, once registries are configured in components.json, install it as @webberui/smooth-follow-cursor.
Usage
import { SmoothFollowCursor } from "@/components/ui/smooth-follow-cursor";
<SmoothFollowCursor color="#8b5cf6" blend className="relative h-[340px] w-full">
{/* your content */}
</SmoothFollowCursor>;The cursor effect only applies inside this container: the container applies cursor-none to hide the native cursor, which comes back as soon as you leave. Touch devices (pointer: coarse) disable it automatically and keep the native cursor.
Examples
Enable it only in the hero
The effect only applies inside the wrapped container, so wrap the homepage hero and the rest of the page keeps the native cursor.
import { SmoothFollowCursor } from "@/components/ui/smooth-follow-cursor";
export function Hero() {
return (
<SmoothFollowCursor className="relative flex min-h-[70vh] items-center justify-center bg-neutral-950">
<h1 className="text-5xl font-semibold text-white">Brand design and web development</h1>
</SmoothFollowCursor>
);
}Mixed light and dark backgrounds with blending
blend puts the cursor layer on mix-blend-difference, so it stays visible over both black and white areas.
<SmoothFollowCursor blend color="#ffffff" dotColor="#ffffff" className="relative h-96 w-full">
<div className="grid h-full grid-cols-2">
<div className="bg-white" />
<div className="bg-black" />
</div>
</SmoothFollowCursor>A minimal ring cursor without deformation
deform={false} turns off velocity stretching; with a smaller size and dotSize you get a plain trailing ring.
<SmoothFollowCursor
deform={false}
size={24}
dotSize={4}
color="#0ea5e9"
dotColor="#0ea5e9"
className="relative h-80 w-full"
>
{/* your content */}
</SmoothFollowCursor>Props
| Prop | Type | Default | Description |
|---|---|---|---|
color | string | "#6366f1" | Blob outer ring color |
dotColor | string | "#6366f1" | Center dot color |
size | number | 38 | Outer ring diameter (px) |
dotSize | number | 7 | Center dot diameter (px) |
deform | boolean | true | Whether to stretch and deform along the direction of travel by speed |
stretch | number | 0.4 | Maximum stretch amount (0–1) |
blend | boolean | false | Inverts and blends colors with mix-blend-difference |
children | ReactNode | — | Container content |
Accessibility
- When the user has "reduce motion" enabled at the system level, the custom cursor is disabled and the native cursor is kept
- Touch devices disable it automatically, and
overflow-hiddenmakes sure the outer ring cannot spill out of the container while deforming - The cursor layer is a purely visual overlay carrying
aria-hiddenandpointer-events-none, so it does not affect interaction with the layer underneath
FAQ
Does it work with the Next.js App Router?
Yes. The file starts with "use client", so import it from a Server Component page as usual. The first render matches the server output, and the reduced-motion check only runs after mount, so it does not cause a hydration mismatch.
Can I apply it to the whole site?
It only takes effect inside its own container and applies overflow-hidden to that container. You can wrap your outermost layout for a full-page effect, but keep in mind that overflow-hidden affects sticky or overflowing content inside it.
What format should color use?
When blend is off, the ring's background is color with 1a appended as alpha, so use a 6-digit hex value such as #8b5cf6. With blend on, the ring background uses color directly.
How do I tune the stretch?
stretch sets the maximum stretch (0–1, default 0.4); higher values give a softer tail. deform={false} disables deformation entirely.
What happens on touch devices and with reduced motion?
Only mouse pointers drive the cursor layer, and touch devices (pointer: coarse) keep the native cursor. When the system "reduce motion" setting is on, the component renders a plain container with your content and no custom cursor.
Confetti Feedback
A hand-built particle confetti celebration — bursting from an origin point, each piece with its own initial velocity, gravity, rotation, and drift, updated on rAF and reclaimed once it lands.
Splash Cursor
Cursor movement produces fluid splashes and ripples, approximating a fluid simulation with canvas 2D.