Wobble Card — Free HTML CSS JS Jelly Hover Snippet

Wobble Card · Cards · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Opposing-layer squish
Shell and content move opposite for jelly feel.
Spring easing
An overshooting cubic-bezier bounces back.
Real 3D parallax
perspective + preserve-3d give true depth.
Pointer-follow lag
A short transition softly chases the cursor.
Hover guard
A flag keeps the spring-back clean.
Depth texture
A dotted pattern and orb reveal the deform.
Grab cursor cues
grab/grabbing hint at pushability.
Single handler
One pointermove drives both layers.

About this UI Snippet

Wobble Card — Jelly Pointer-Follow with Counter-Parallax

Screenshot of the Wobble Card snippet rendered live

The wobble card is the playful hover effect where a card squishes and leans toward your pointer like a block of soft jelly, while its contents drift the opposite way for a gooey parallax — then everything springs back when you leave. This snippet builds it with plain HTML, CSS, and one vanilla JavaScript pointer handler, relying on a spring-like easing curve for the bouncy feel.

Two layers moving in opposition

The effect's secret is that the shell and the content move in opposite directions. A pointermove handler converts the cursor position to -0.5…0.5 fractions, then translates and tilts the outer .wo-card toward the pointer (translate3d plus rotateX/rotateY), while translating the inner .wo-inner by a larger amount in the negative direction. Because the content slides against the card's lean, the surface appears to stretch and the text appears to resist — the visual signature of squishy, deformable material rather than a rigid tilt.

The spring easing

Both layers transition with cubic-bezier(.2, .8, .2, 1), an ease-out curve that overshoots slightly and settles — the closest you get to a spring without a physics library. During movement the short .2s transition keeps the card chasing the pointer with a soft lag, and on release the same curve makes it bounce back to rest rather than snapping linearly. This single easing choice is what makes it feel like jelly instead of glass.

Perspective and preserve-3d

The stage sets perspective: 1200px and the card uses transform-style: preserve-3d, so the rotateX/rotateY produce genuine depth and the content's counter-translation reads as parallax within the card rather than a flat slide. Without the perspective parent, the rotation would look like a 2D skew.

A hovering guard

The handler only wobbles while a hovering flag is true, set on pointerenter and cleared in reset() on pointerleave. This prevents stray moves (for example, during the spring-back transition) from re-triggering the wobble, so the return-to-rest animation always completes cleanly.

Decorative depth cues

A blurred white .wo-orb in the corner and a faint dotted texture (::after radial-gradient tiled at 18px) give the surface something to deform, so the parallax is visible. These sit at different effective depths from the text, reinforcing the soft-3D illusion as the card moves. The cursor: grab/grabbing states hint that the card is something you can push around.

Customizing it

Tune the 18/12/22 multipliers to control how far the shell leans, how much it tilts, and how strongly the content counter-moves — increasing the gap between the shell and inner factors makes the squish more pronounced. Adjust the cubic-bezier for a stiffer or bouncier spring, and recolor the gradient. Pair it with a glare card or a pin card for a set of tactile cards, or use it as an interactive feature cards tile.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Ask an AI coding assistant like Claude to explain why the shell and the inner content translate in opposite directions on pointermove — walk through the px/py fractions and the opposite-sign multipliers together to see exactly why that counter-motion is what reads as squishy jelly rather than a rigid tilt. It's worth asking about the hovering guard flag too: trace what would go wrong during the spring-back transition if pointermove events weren't gated behind it. For extending the card, ask for a version that also scales slightly larger on hover for added depth, multiple wobble cards in a grid where only the hovered one responds, or a touch-compatible fallback using device orientation instead of pointer position on mobile. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a "jelly" hover card in plain HTML, CSS, and JavaScript that squishes and leans toward the cursor with counter-parallax content — using CSS 3D transforms and a single pointermove handler, no physics library.

Requirements:
- A stage element with CSS perspective set, containing a card with transform-style: preserve-3d, so 3D rotations applied to the card produce genuine depth rather than a flat 2D skew.
- On pointermove over the card, convert the cursor's position into fractions from -0.5 to 0.5 across the card's width and height using its bounding rect.
- Apply a combined translate3d and rotateX/rotateY transform to the outer card that leans and shifts toward the cursor based on those fractions, while applying an independent transform to an inner content wrapper that moves by a larger amount in the opposite direction — the outer shell and inner content must visibly move counter to each other, not together.
- Give both the outer and inner transforms a short CSS transition using an ease-out cubic-bezier curve that slightly overshoots before settling, so the motion reads as a soft spring rather than a linear tween, both while tracking the cursor and when resetting on pointer leave.
- Track a boolean hovering flag set on pointerenter and cleared in a reset function on pointerleave, and gate the pointermove handler's transform updates behind that flag so stray movement during the spring-back transition can never re-trigger or interrupt the reset.
- Add at least one decorative depth cue inside the card (such as a blurred glowing orb or a subtle dot-grid texture) so the parallax squish between the shell and the content is visually apparent as the pointer moves, not just theoretical.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA gradient card renders at rest.
  2. 2
    Drag your pointer across itThe card squishes and leans toward the cursor.
  3. 3
    Watch the contentThe text drifts the opposite way like soft parallax.
  4. 4
    Leave the cardEverything springs back on a bouncy easing.
  5. 5
    Adjust the squishChange the shell and inner translate multipliers.
  6. 6
    Tune the springEdit the cubic-bezier for stiffer or bouncier motion.

Real-world uses

Common Use Cases

Playful feature tiles
Liven up a feature cards grid.
Product highlights
Pair with a glare card showcase.
Bento sections
A tactile cell inside a bento grid.
Landing CTAs
Wrap a shimmer button call to action.
Portfolio cards
Make project tiles feel interactive.
Hover-physics demos
A reference for spring-eased pointer follow.

Got questions?

Frequently Asked Questions

Two things: the shell and the inner content translate in opposite directions on pointer move, so the surface appears to stretch and the text resists, and both layers use a spring-like cubic-bezier(.2,.8,.2,1) that overshoots and settles. The opposing motion plus the bouncy easing read as soft, deformable material rather than a rigid tilt.

The pointermove handler leans the outer card toward the cursor while translating the inner content by a larger amount in the negative direction. Inside the perspective and preserve-3d context, the content's opposite slide reads as parallax depth within the card, which is what sells the squish.

It ensures only deliberate hovers wobble the card. The flag is set on pointerenter and cleared on pointerleave inside reset(), so stray pointer moves — for instance during the spring-back transition — don't re-trigger the effect and interrupt the return-to-rest animation.

No. The bounce comes entirely from the CSS cubic-bezier(.2,.8,.2,1) transition, an ease-out curve that slightly overshoots before settling. It approximates a spring closely enough for hover feedback without the cost or complexity of a real physics engine.

Render the card and inner content as a component, keep the perspective and preserve-3d CSS, and attach pointerenter, pointermove, and pointerleave handlers that write transforms via refs so they don't trigger re-renders. Keep the hovering flag in a ref. In Tailwind, use perspective and transform utilities with a custom spring easing defined via arbitrary transition-timing-function values.