Tilt Glow Card — Free HTML CSS JS 3D Hover Card Snippet

Tilt Glow Card · Cards · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Cursor-aware 3D tilt
rotateX and rotateY map to pointer position.
Pointer-tracking glow
A radial gradient driven by CSS variables.
Parallax content layer
translateZ floats the body above the card.
GPU-only animation
Only transform changes — no reflow.
Perspective depth
perspective() makes the tilt read as 3D.
Smooth reset
mouseleave settles the card back flat.
Single config constant
One MAX value controls tilt intensity.
Content-agnostic
Wrap any markup in the card.

About this UI Snippet

Tilt Glow Card — A 3D Card That Leans Into the Cursor

Screenshot of the Tilt Glow Card snippet rendered live

The tilt glow card is the interactive product card that rotates in 3D space toward your pointer while a soft radial glow follows underneath — the effect popularised by modern SaaS and developer-tool landing pages. This snippet builds it with plain HTML, CSS 3D transforms, and a small vanilla JavaScript mousemove handler, with no library or canvas.

The 3D tilt math

On every mousemove the handler reads the card's getBoundingClientRect() and converts the cursor position into two normalised ratios from 0 to 1 across the width and height. Those ratios are mapped to rotateX and rotateY angles, deliberately inverted on each axis so the corner under the pointer lifts toward you rather than away — that inversion is the difference between a tilt that feels physical and one that feels wrong. The transform is applied with a perspective(800px) prefix so the rotation reads as depth instead of a flat skew.

The pointer-tracking glow

A separate absolutely-positioned .tg-glow layer holds a radial-gradient whose centre is driven by two CSS custom properties, --mx and --my. The same handler writes the cursor percentage into those variables, so the highlight slides under the cursor in real time. The glow only fades in on :hover via an opacity transition, which keeps the resting card clean and makes the light feel like it switches on as you approach.

Layered depth with translateZ

The inner content sits on its own layer pushed forward with transform: translateZ(40px) inside a transform-style: preserve-3d parent. Because the content lives closer to the viewer than the card surface, it parallaxes slightly as the card rotates, giving the title and button a genuine sense of floating above the panel rather than being painted onto it.

Smooth, cheap, and jank-free

The tilt transition is intentionally short (about 120ms) so the card chases the cursor responsively without lagging, and will-change: transform hints the compositor to promote the card to its own layer. Because only transform and a couple of custom properties change per frame, the browser never reflows or repaints layout — the whole effect runs on the GPU. On mouseleave the transform resets to zero so the card settles flat.

Customizing it

Tune the MAX constant to make the tilt subtler or more dramatic, change the glow colour and radius in the gradient, or adjust translateZ to push the content further forward. Drop in any content — pricing, a feature, an avatar — and the effect still works. Pair it with a spotlight card grid or a pricing card section for an interactive landing page.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Have an AI coding assistant like Claude explain why rx and ry are computed as (0.5 - py) and (px - 0.5) rather than the more obvious (py - 0.5) and (0.5 - px) — the inversion is subtle but it's the exact reason the corner under the cursor lifts toward you instead of tilting the wrong way. It's also a good check for efficiency: confirm that only transform and two CSS custom properties change per mousemove, and ask whether will-change: transform is actually helping here or just consuming extra compositor memory for no benefit. For extending it, ask for a version where the glow color shifts based on tilt angle, a card that tracks the pointer even when the mouse enters at speed (using pointer events instead of mouse events for better touch support), or a whole grid of these cards where only the hovered one tilts. 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 3D tilt card that leans toward the cursor with a pointer-tracking glow, in plain HTML, CSS, and JavaScript using only CSS transforms — no canvas, no library.

Requirements:
- On mousemove over the card, read the card's bounding rect and convert the cursor's position into two ratios from 0 to 1 across the card's width and height.
- Map those ratios to rotateX and rotateY angles, inverting each axis relative to the naive mapping so the corner nearest the cursor visually lifts toward the viewer rather than tilting away, and apply the rotation with a perspective() prefix on the same transform so it reads as real depth rather than a flat skew.
- Add a separate absolutely-positioned glow layer with a radial-gradient background whose center position is controlled by two CSS custom properties; update those two properties from the same mousemove handler so the glow visibly follows the cursor in real time, and only reveal the glow via an opacity transition on hover.
- Put the card's inner content (title, text, button) in its own layer pushed forward with translateZ inside a parent using transform-style: preserve-3d, so the content appears to float above the card surface with a slight parallax as it rotates.
- Keep the tilt transition short (around 120ms) so the card visibly chases the cursor without lag, and reset the transform to flat (zero rotation) on mouseleave.
- Ensure the only properties that change per animation frame are the transform and the two custom properties — no layout-triggering properties — so the whole effect can run on the compositor.

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 pricing-style card renders, flat at rest.
  2. 2
    Hover the cardIt tilts toward the cursor and a glow fades in.
  3. 3
    Move the pointer aroundThe tilt and glow follow the cursor in real time.
  4. 4
    Move the cursor awayThe card settles smoothly back to flat.
  5. 5
    Adjust the tiltChange the MAX constant for more or less rotation.
  6. 6
    Swap the contentDrop in any card body — the effect still works.

Real-world uses

Common Use Cases

Pricing tiers
Make a pricing card interactive.
Feature highlights
Tilt a spotlight card on hover.
Product showcases
Lift a product card toward the user.
Portfolio grids
Add depth to focus cards.
Hero callouts
A floating panel above a gradient mesh hero.
Dashboards
Make a glass stat card feel tactile.

Got questions?

Frequently Asked Questions

On each mousemove the handler reads getBoundingClientRect() and turns the cursor position into ratios from 0 to 1 across the card. Those ratios map to rotateX and rotateY angles, inverted per axis so the corner under the pointer lifts toward you. A perspective(800px) prefix turns the rotation into real depth instead of a flat skew.

A separate glow layer holds a radial-gradient centred on two CSS custom properties, --mx and --my. The same mousemove handler writes the cursor percentage into those variables, so the highlight slides under the pointer. It fades in only on hover via an opacity transition, so the resting card stays clean.

The inner content is pushed forward with translateZ(40px) inside a transform-style: preserve-3d parent. Because it sits closer to the viewer than the card surface, it parallaxes as the card rotates, giving the title and button a genuine floating feel rather than looking painted on.

No. Only the transform and two custom properties change per frame, so the browser never reflows or repaints layout — the work runs on the GPU compositor. will-change: transform promotes the card to its own layer, and a short transition keeps it chasing the cursor responsively without lag.

Attach onMouseMove and onMouseLeave handlers to the card element via a ref. Compute the rotation from the event and the ref's bounding rect, then write the transform and CSS variables imperatively on the ref rather than through state, so you do not re-render on every pointer move. The 3D and gradient CSS port unchanged; in Tailwind use perspective and transform utilities with arbitrary values.