Circle fill button
A circle fill button grows a circular fill from where the pointer enters, then covers the control. The press still has to land on the same box.
clip-path circleAlso called Radial fill button, Ripple fill, Pointer fill, Circular wipe.
Here it is working.
Hover from different sides. The disc starts where you enter.
For designers
The circle is paint inside a real button. The live Button page still owns the label, hierarchy, loading and the focus ring. Magnetism moves the control. The circle stays inside the clip. The resting fill has to work for thumbs, because there is no pointer to grow from. Origin the circle on the entry point, not the centre every time, or it reads as a canned ripple. A circle that escapes the radius looks like a leak. One of these on a hero can take the extra attention. Four in a row will fight.
When to use circle fill button
Use this when
- There is one obvious action on a spacious screen, and hover is a real input.
- You want the fill to admit where someone pointed, without moving the target.
- The label stays readable as the circle crosses it.
- Touch and keyboard can use the button with no circle at all.
Reach for something else when
- A straight wipe from one edge would do. Use Background fill button.
- The fill should sweep on a curve. Use Curve fill button.
- The button itself should move. Use Magnetic button.
- The question is still the component. Start with the Button page.
How to build it
Start with a real button. Put a circle behind the label and clip it to the button. On pointer enter, read the position inside the box, place the circle there, and scale it until the button is covered. quickTo helpers keep that from queuing a tween per pixel if you also track move. A 200 to 300 millisecond ease is enough. Leave the hit target where it was. Invert the label as the circle covers it, or pick two fills that both clear 4.5:1. Ignore the effect on touch. Keyboard focus should look like the live Button focus ring. On reduced motion, snap to the hover fill or skip it.
Official GSAP
gsap.to on clip-path, with the circle centred where the pointer entered.
const at = `${pointerX}px ${pointerY}px`;
gsap.set(fill, { clipPath: `circle(0% at ${at})` });
gsap.to(fill, { clipPath: `circle(150% at ${at})`, duration: 0.45, ease: 'power2.out' });Every plugin ships in the public GSAP package. Nothing here is copied from a paid pack.
Common questions
- Is this a ripple?
- A ripple is usually a press flash that fades. This is a hover fill that grows from the pointer and stays while you are over the control.
- How big does the circle need to be?
- Large enough to cover the farthest corner from the entry point.
- What about mobile?
- Nothing. There is no pointer.
- Does the focus ring follow the circle?
- No. Keep the ring on the layout box.
- Should the circle start from the centre?
- Only if you never have a pointer position. From the entry point feels aimed.
Save as skill
A SKILL.md for this one animation: what it is, the official docs link, and a copy-paste block with the reduced-motion branch already in it. Copy gives you the same words.
Use this with your AI
Save the skill, drop it into Cursor, Claude, or whatever you use, and ask for this motion. That is all. The skill tells the agent to open this page, watch the working demo, and match it.
Last reviewed 26 AUG 2026
Next: Curve fill button