Category 03 · Pointer craft

Hover & Cursor Interactions

Hover is where motion stops being decoration and becomes feedback. A card that responds within 100ms feels like software; the same card with a 500ms spring feels like a demo. This guide covers the pattern families, their touch fallbacks, and the timings that make components feel solid.

Card-shaped panel tilted in perspective with a bright yellow-green edge highlight, illustrating a 3D tilt hover effect
3D Tilt reads best at small angles — 4 to 8 degrees is usually the whole effect.

The pattern families

Magnetic Hover. The element translates a few pixels toward the pointer, as though attracted. Applied to buttons it makes targets feel eager; applied to everything it makes a page feel unstable. Cap displacement at 4–10px and always return to the exact origin on pointer leave, or repeated hovers will drift the element out of alignment.

3D Tilt. Rotation on two axes driven by pointer position inside the element's bounds, with a perspective of roughly 600–900px. Works well on media-led cards and product tiles. It needs a highlight that moves with the tilt — without a specular cue, the rotation looks like a rendering glitch rather than a surface.

Glass Distortion. A frosted overlay whose blur radius, brightness or backdrop offset shifts on hover. Cheap when you animate opacity of a pre-blurred layer; expensive when you animate backdrop-filter values directly, which can force the compositor to re-blur a large region every frame.

Cursor followers. A custom dot, ring or label that trails the pointer and changes state over interactive elements. High-impact for portfolio and agency work, and genuinely risky elsewhere: hiding the native cursor removes an OS-level accessibility affordance, and lag between the real pointer and the drawn one is perceived as input latency.

Micro-interactions. Icon state changes, underline wipes, toggle springs, counter ticks, copy-to-clipboard confirmations. Individually trivial, collectively the difference between an interface that feels maintained and one that does not.

Comparison

Hover pattern trade-offs
PatternTypical durationTouch fallbackAccessibility note
Magnetic Hover120–180ms out, 240ms returnStatic offset or noneMust not move the click target away
3D TiltFollows pointer, 200ms settleDisable entirelyKeep text upright and legible
Glass Distortion160–240msShow final stateMaintain 4.5:1 text contrast in both states
Cursor followerContinuous, 60–120ms lerpNever shownNever hide the system cursor outright
Micro-interaction100–200msBind to active stateMirror on :focus-visible

Asymmetric timing is the trick

The most useful single rule in this category: make the entry faster than the exit. A hover state that arrives in 120ms and leaves in 240ms feels responsive on approach and calm on departure. Reverse those numbers and the same component feels sticky. The same asymmetry applies to pressed states — snap in, ease out.

Transition only the properties you are changing. transition: all is the most common source of accidental animation: add a border on hover later and it will now animate too, often with a visible reflow. Naming properties also documents intent for the next person reading the file.

Pros and cons of pointer-driven effects

In favour

  • Immediate feedback reduces the perceived latency of the whole interface.
  • Hover states can carry information — affordance, direction, destination.
  • Effects are self-limiting: they only run while the pointer is present.

Against

  • Roughly half of traffic has no hover at all, so the effect must never carry unique meaning.
  • Pointer-tracking effects run per frame and can idle a CPU core while a user simply reads.
  • Custom cursors and magnetic buttons interfere with precision input and assistive tooling.

Keyboard and touch parity

Every hover state needs a focus equivalent. Use :focus-visible so mouse users do not see focus rings on click, but never remove the outline without a visible replacement — a colour change alone often fails contrast requirements. If a card reveals its description on hover, that description must also be present in the accessible name or visible by default on touch.

Gate pointer-only effects behind capability queries rather than screen width. @media (hover: hover) and (pointer: fine) is the correct test; a large touchscreen is wider than a small laptop, so width tells you nothing about input. On the JavaScript side, prefer pointer events over separate mouse and touch handlers.

Performance notes

Keep pointer handlers cheap: read the element's bounds once on mouseenter and on resize, then use cached values inside the move handler. Write transforms in a single requestAnimationFrame callback per frame rather than on every event. Use will-change: transform only for the duration of the interaction — leaving it on permanently across dozens of cards allocates compositor layers you never use and can increase memory pressure noticeably on low-end devices.

Finally, budget the whole page rather than the component. Twenty cards each with a tilt handler, a glass overlay and a shadow transition will feel worse than five cards with one well-tuned effect, no matter how correct each individual implementation is.