15 CSS 3D Tilt Hover Cards

15 hand-coded CSS 3D tilt hover cards you can copy-paste into any project — e-commerce product spotlight, glassmorphism parallax team card, SaaS pricing tier, holographic NFT collectible with conic-gradient foil, pop-out character mascot, dark tech grid with border-glow-follows-cursor, media player album art, blog article preview, cyberpunk neon glow, dashboard KPI widget, minimalist real estate, flip-to-back tilt, mobile app showcase, course learning card, and one Pure CSS touch-friendly tilt (no JS, uses :has() + nine invisible hover zones). Every demo uses the same architecture: Vanilla JS writes four CSS custom properties (--rx/--ry for rotation, --mx/--my for glare position); ALL the rendering stays in CSS on the GPU via transform: perspective() rotateX() rotateY() with transform-style: preserve-3d cascading so inner layers float at their own translateZ() depth. Touch and accessibility guards are non-negotiable: every demo gates the tilt behind @media (hover: hover) and (pointer: fine) AND @media (prefers-reduced-motion: no-preference), so touch users and motion-sensitive users always get the fully-styled static card. Modern platform features throughout: oklch() palettes, color-mix() tints, @property-registered custom properties, conic-gradient holo foil, backdrop-filter glassmorphism, :has() for the pure-CSS variant, aspect-ratio for image slots. Scoped under .thc-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.

1 pure CSS14 light JSPublished

Related33 CSS Card Hover Effects23 CSS Flip Cards20 CSS Cards

E-Commerce Product Spotlight Card — preview
01 / 15Vanilla JS

E-Commerce Product Spotlight Card

A premium product card where the sneaker cutout floats 50px in front of the card face, the Add-to-Cart button rides even higher, and a radial glare chases the cursor. The depth stack — background, product, copy, CTA — is the exact pattern D2C stores use to make a $189 product feel worth it before a single scroll.

Published

Glassmorphism 3D Parallax Team Card — preview
02 / 15Vanilla JS

Glassmorphism 3D Parallax Team Card

A frosted-glass profile card for agency About pages: the avatar ring, name block and social pills each hover at a different translateZ depth behind real backdrop-filter blur, over an oklch aurora that glows through the glass as the card tilts. The gradient hairline border is drawn with the background-clip trick — no extra wrapper.

Published

Interactive Pricing Tier Card — preview
03 / 15Vanilla JS

Interactive Pricing Tier Card

A three-tier pricing row where every card tilts toward the cursor, but the featured Pro tier adds a scale boost and a violet glow that intensifies with hover — the classic SaaS landing-page trick for steering eyes (and clicks) to the plan you want sold. One shared handler drives all three cards.

Published

Holographic NFT Collectible Card — preview
04 / 15Vanilla JS

Holographic NFT Collectible Card

A trading-card-grade holo effect: a conic rainbow foil swings across the artwork as the cursor moves, blended with color-dodge over a deep-space gradient, inside a heavy ±20° tilt. This is the pattern behind every viral 'Pokémon card CSS' demo — rebuilt with oklch stops so the foil never muddies.

Published

Pop-Out Character Mascot Card — preview
05 / 15Vanilla JS

Pop-Out Character Mascot Card

The scroll-stopping agency trick: a mascot cutout whose head rises OUTSIDE the card's top edge, floating at translateZ(70px) while the card tilts beneath it. The illusion needs exactly two decisions — overflow:visible on the card, and a cutout that overlaps the border — and it makes any character IP feel alive.

Published

Dark Mode Tech Feature Grid Card — preview
06 / 15Vanilla JS

Dark Mode Tech Feature Grid Card

The Vercel/Supabase-style feature grid: three near-black cards with a mouse-following border highlight — a radial light that lives IN the border ring and travels along it as the cursor crosses the grid — plus a whisper of tilt (±5°). The technique is one ::before layer and two custom properties per card.

Published

Media Player Album Art Hover Card — preview
07 / 15Vanilla JS

Media Player Album Art Hover Card

A streaming-app album card driven by a requestAnimationFrame spring: instead of CSS transitions, the tilt is lerped every frame toward the pointer, so it overshoots and settles like a physical object. On hover the play button and track controls surface from under the artwork at translateZ(50px).

Published

Interactive Blog Article Preview Card — preview
08 / 15Vanilla JS

Interactive Blog Article Preview Card

An editorial card that respects reading: tilt capped at ±4.5° so the headline never smears, while the cover image lifts on its own Z plane and an author + reading-time metadata row slides up from the card's baseline on hover. The restraint is the lesson — content cards earn trust with millimetres, not theatrics.

Published

Cyberpunk Neon Glow Interactive Card — preview
09 / 15Vanilla JS

Cyberpunk Neon Glow Interactive Card

An event-promo card whose neon reacts physically: the magenta/cyan box-shadow's offset is computed FROM the tilt — light the card banks away from throws a longer glow on the opposite side, like a sign swinging in front of a wall. A scanline overlay and flickering border finish the Night City read.

Published

Dashboard Analytics KPI Widget Card — preview
10 / 15Vanilla JS

Dashboard Analytics KPI Widget Card

A FinTech KPI widget with enterprise-grade restraint: perspective(1600px) with tilt capped at ±4°, a drop-shadow that deepens as the card lifts 6px on hover, and a CSS-only sparkline of flex bars that stagger-grow when the tilt arms. Proof that 3D belongs in dashboards — at homeopathic doses.

Published

Minimalist Architecture Real Estate Card — preview
11 / 15Vanilla JS

Minimalist Architecture Real Estate Card

A luxury listing card built on absence: acres of white, one hairline rule, serif numerals — and a property photo that lives in grayscale until hover drains the filter away as the card tilts a fluid ±7°. The grayscale-to-color transition is doing the persuasion; the 3D just makes it feel hand-held.

Published

Flip-to-Back 3D Tilt Card — preview
12 / 15Vanilla JS

Flip-to-Back 3D Tilt Card

Tilt and flip in one transform: the card follows the cursor like any tilt card, but click (or press Enter/Space) and it swings a full 180° to reveal contact details on its back — and keeps tilting while flipped. The trick is composing rotateY(flip + tilt) as a single calc(), never two competing transforms.

Published

Mobile App Showcase Screen Card — preview
13 / 15Vanilla JS

Mobile App Showcase Screen Card

An app-landing-page hero card: a CSS-drawn phone hovers at a resting 3D angle inside the card, straightening toward the viewer as the cursor approaches centre, while a rating pill and a downloads badge orbit at translateZ(70px) and a specular streak sweeps the screen glass. High perspective depth, floating chrome — the App Store screenshot, weaponized.

Published

Course Skill Learning Card — preview
14 / 15Vanilla JS

Course Skill Learning Card

An EdTech course card where progress is the hero: a 68%-complete pill floats above everything at translateZ(40px), the progress bar's fill glints as the card tilts, and module metadata sits calmly at a lower depth. Built for course catalogs where a dozen of these share a grid — so the motion budget is deliberately mid-range.

Published

Pure CSS Touch-Friendly Tilt Card — preview
15 / 15Pure CSS

Pure CSS Touch-Friendly Tilt Card

Zero JavaScript, zero listeners: a 3×3 grid of invisible hover zones overlays the card, and :has() maps whichever zone the cursor occupies to a predefined tilt pose — nine discrete poses that eased transitions blend into motion that feels continuous. The accessible, dependency-free fallback every tilt collection needs.

Published

FAQ

Frequently asked questions

What is a CSS 3D tilt hover card and how does the effect work?
A CSS 3D tilt hover card is a component that rotates in 3D space to follow the user's cursor — the card face turns 10-14° toward the pointer, layered content (buttons, badges, product images) floats out in front of it via translateZ(), and a specular glare chases the cursor across the surface. Every demo in this collection uses the same architecture: JavaScript does exactly one job — measure the pointer's position and write four CSS custom properties on the card element (--rx/--ry for rotation, --mx/--my for glare position). ALL the visual rendering stays in CSS: transform: perspective(1100px) rotateX(var(--rx)) rotateY(var(--ry)) on the card, plus transform-style: preserve-3d cascading through the child tree so each element can float at its own depth via translateZ(). Because transforms are compositor-friendly, the animation runs on the GPU thread — not the main thread — so it stays 60fps even on mid-tier mobile, doesn't block INP, and doesn't cause layout shift (Core Web Vitals CLS stays 0). Every demo is graded on four axes: (1) MODERN CSS — @property-typed custom properties, oklch() palettes, color-mix() tints, conic-gradient holo foil, backdrop-filter glass, :has() for the Pure CSS variant. (2) TOUCH + ACCESSIBILITY — every demo gates the tilt behind @media (hover: hover) and (pointer: fine) AND @media (prefers-reduced-motion: no-preference), so touch users and motion-sensitive users always get the fully-styled static card. Interactive cards are real <a>/<button> elements or tabindex="0" with visible :focus-visible rings; decorative layers are aria-hidden. (3) PERFORMANCE — transform-only rendering, no layout thrash, and pointer events + getBoundingClientRect() per move (never cached — cached rects break on scroll or resize). (4) DROP-IN PORTABILITY — every demo themes from 3-6 CSS custom properties on the .thc-NN root; retune the palette by changing 3-6 tokens without touching the tilt math.
How do I add a 3D tilt hover effect without using vanilla-tilt.js or tilt.js?
You don't need a library — the Vanilla JS in every demo below is 15-25 lines and hasn't changed shape since 2020. The pattern: on pointermove, get the card's bounding rect once, calculate the pointer's normalized position (0-1 across width and height), map that to rotation degrees with a MAX constant (10-14° reads premium, 20°+ reads playful), and write the result to CSS custom properties. On pointerleave, drop an is-live class that re-arms a slow spring transition and reset the properties to 0. All the visual work — perspective, rotation, per-layer translateZ, glare gradient — lives in CSS. Compared to vanilla-tilt.js: our approach is ~15 lines vs their 800+, ships zero KB of library dependency, uses modern pointer events (works with pen and touch input correctly), and integrates cleanly with your CSS custom-property design tokens. Compared to tilt.js (the jQuery-era version): our approach doesn't require jQuery, uses transform not top/left (compositor-friendly vs layout-thrashing), and honors prefers-reduced-motion out of the box. Compared to react-parallax-tilt: our approach works in vanilla HTML, any framework, or SSR — no hydration required, no useState/useEffect dance, no client:only directive.
How do I ship a tilt card that stays accessible for touch users and motion-sensitive users?
Three guards, all shipped in every demo below. (1) TOUCH GUARD — the JS bails out early on if (!matchMedia('(hover: hover) and (pointer: fine)').matches) return;. Touch users have no pointer to hover with; forcing tilt via touchmove would either fight the browser's native scroll or feel jittery. Touch users get the fully-styled STATIC card exactly as it renders at rest — same background, same layers, same button. (2) REDUCED-MOTION GUARD — if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;. Vestibular-disorder users have opted out of motion at the OS level (Windows Reduce Motion, macOS Reduce Motion, iOS Reduce Motion); WCAG 2.3.3 requires we honor that. Same outcome as touch users — static, fully styled card. (3) FOCUS GUARD — every interactive card is a real <button>, <a>, or tabindex="0" with a visible :focus-visible outline. Screen readers announce the card name via aria-label; decorative layers (glare overlays, badges, product mockups) carry aria-hidden="true" so they don't clutter the accessibility tree. This trio is not optional — a tilt effect that only works with a mouse-and-fine-pointer and traps focus is a WCAG 2.1 conformance failure and a bad user experience for the 25-40% of your audience on touch devices. Every demo in this collection ships all three guards by default.
How do I do a Pokémon-style holographic tilt card in CSS?
Demo 04 (Holographic NFT Collectible Card) is the reference implementation. Two layers stack: (1) the CARD FACE itself with the standard tilt transform, and (2) a HOLO OVERLAY — a conic-gradient painted with oklch() stops that runs the full spectrum, positioned absolutely inside the card with pointer-events: none; mix-blend-mode: color-dodge; opacity: 0.6. The conic-gradient's from angle is bound to a @property-registered custom property so it can animate smoothly, and the whole overlay's position tracks the same --mx/--my variables as the glare. When the card tilts, the holographic rainbow shifts across the surface exactly like a real Pokémon holo card catches light from different angles — because the physics is analogous (angle-dependent reflection). The trick to making it feel expensive rather than tacky: keep the opacity under 0.7, use mix-blend-mode: color-dodge (not screen or overlay — dodge preserves the underlying palette better), and register the conic angle with @property --holo-angle { syntax: '<angle>'; inherits: false; initial-value: 0deg } so animations interpolate smoothly. This exact recipe is what OpenSea NFT card previews, web3 collectible marketplaces, and the growing category of digital trading-card sites use. Baseline requirements: @property (Chrome 85+, Safari 16.4+, Firefox 128+), mix-blend-mode universal, conic-gradient universal since 2020.
How do I ship a SaaS pricing table with 3D tilt cards (Stripe/Linear/Vercel/Notion style)?
Demo 03 (Interactive Pricing Tier Card) is the modern SaaS pricing pattern. Three key techniques: (1) TILT AMOUNT dialed DOWN to 6-8° (not 14°) — pricing tables are high-trust surfaces where dramatic tilt reads as gimmicky; subtle tilt reads as attention to detail. (2) FEATURED TIER emphasis via scale(1.05) at rest plus a stronger accent glow — the middle tier that most SaaS wants users to pick. (3) BILLING-CADENCE toggle (monthly/annual) as a real <input type="checkbox"> or <input type="radio"> pair with :checked ~ .prices CSS selector sibling combinator — the price updates without JavaScript. Every price is font-variant-numeric: tabular-nums so digits don't jiggle on toggle. Feature-list bullets use display: grid; grid-template-columns: 20px 1fr for icon + text alignment (subgrid on newer browsers for cross-tier alignment). The CTA button on each tier translates to translateZ(30-40px) so it floats above the card face — the visual affordance that says 'this is the primary action.' This is the exact pattern Stripe (stripe.com/pricing), Linear (linear.app/pricing), Vercel (vercel.com/pricing), Notion (notion.so/pricing), and Airtable ship. Combine with the shimmer skeleton loader pattern (CSS Shimmer Skeleton Cards Demo 04) for the loading state while pricing data fetches from your backend.
How do I use --rx/--ry CSS custom properties for the tilt transform (bridging JS to CSS)?
This is the load-bearing architectural decision in every demo. The pattern: JavaScript writes four custom properties on the card element via card.style.setProperty('--rx', value + 'deg'). CSS reads them via transform: perspective(1100px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)). The 0deg fallback in var() means the card renders correctly even before JS attaches (no flash of un-tilted content). To make the transitions feel physical rather than robotic: two CSS classes with different transition durations. Default: transition: transform 0.6s cubic-bezier(0.2, 0.9, 0.3, 1.15) — the springy return-to-rest curve when the pointer leaves. Active (class is-live, added during pointer movement): transition: transform 0.08s linear — near-instant so the tilt feels responsive to the pointer. The JS toggles is-live on pointermove and removes it on pointerleave. Optional upgrade: register the properties with @property --rx { syntax: '<angle>'; inherits: false; initial-value: 0deg } — this makes them animatable via @keyframes too, and prevents 'accidentally set to a string' bugs by making the browser type-check. Baseline: @property is Baseline widely-available since 2024 (Chrome 85, Safari 16.4, Firefox 128).
How do I ship a border-glow-follows-cursor effect on a dark-themed card?
Demo 06 (Dark Mode Tech Feature Grid Card) is the reference. The trick: a ::before pseudo-element positioned inset: -1px on the card, with background: radial-gradient(150px circle at var(--mx) var(--my), oklch(0.72 0.15 160), transparent 50%). The gradient is a small bright disc positioned at the pointer's location (bound to the same --mx/--my variables as the glare), rendered BEHIND the card face via z-index: -1 or ::before stacking order. Because the gradient is a fixed-size disc following the pointer, the visible portion looks exactly like a light source ILLUMINATING the card's edge from wherever the cursor is. Combined with a backdrop-filter: blur(20px) on the card face, the glow reads as a real physical light interacting with a glass surface. This is the pattern that Linear, Vercel, and Framer all ship on their dark-themed feature cards. Two gotchas: (1) the ::before element MUST have pointer-events: none or it will eat clicks; (2) the color-mix tint on the gradient stop should stay under 60% saturation — a 100%-saturated glow reads as neon and cheapens the effect.
Can I do a 3D tilt card in pure CSS without any JavaScript?
Yes — Demo 15 (Pure CSS Touch-Friendly Tilt Card) is the reference. The technique: nine invisible hover zones (a 3×3 grid of transparent <div> elements positioned absolutely over the card face) and the :has() selector to detect which zone the cursor is in. Each zone triggers a different pre-defined tilt pose: top-left zone rotates +12° X / +12° Y, center zone stays flat, bottom-right rotates -12° X / -12° Y, etc. The transitions blend between poses smoothly, so the card appears to follow the cursor even though it's actually snapping between 9 fixed states. Combined with a longer transition duration (~200ms) the illusion is nearly indistinguishable from JS-driven continuous tilt. Baseline requirements: :has() is Baseline widely-available (Chrome 105+, Safari 15.4+, Firefox 121+). Trade-offs vs the JS approach: (a) resolution is limited to 9 poses per card — smooth but not pixel-perfect pointer tracking; (b) no glare position tracking (you can add a slower CSS-only radial-gradient shift via @keyframes but it won't chase the cursor); (c) works with keyboard focus too if you replace the hover zones with tabindex elements (bonus accessibility win). For copy-paste sites, gaming portfolios, and any surface where 'no framework, no library, no build step' is the constraint — this is the right recipe.
Do these tilt cards work in React / Next.js / Vue / Svelte / Astro?
Yes — every demo is framework-agnostic HTML + CSS + Vanilla JS. Copy the HTML into a component template, lift the CSS into a scoped styles block, and paste the JS into a useEffect (React), onMount (Svelte / Vue), or <script> tag (Astro). The pattern that keeps it framework-clean: the entire tilt logic is scoped by document.querySelector('.thc-NN .thc-NN__card'), so if you rename the class prefix to match your framework's conventions (BEM, CSS Modules, styled-components), just update the selector. React specifics: wrap the JS in a useEffect(() => {...}, []) and add cleanup in the return to remove event listeners. Next.js App Router: works in Client Components ('use client' directive) — the demo won't work in Server Components because there's no window/document. Svelte / SvelteKit: use bind:this={cardEl} instead of querySelector for the ref. Astro: works out of the box with a <script> tag; the tilt initialization runs after hydration. Because the effect is pure Vanilla JS with no dependencies, you avoid the class of 'tilt library conflicts with framework SSR' bugs that plague vanilla-tilt.js, react-parallax-tilt, and Framer Motion tilt patterns.

Related collections

24 CSS Animated Cards preview

24 CSS Animated Cards

24 hand-coded CSS animated card patterns organised by what triggers the motion, not by card style. Scroll and entrance triggers: staggered grid reveals, @starting-style mount-in, scroll-driven scale and fade on animation-timeline: view(), View Transitions API card-to-detail morphs, blur-to-sharp lazy image loading, and FLIP re-layout when a filter changes. State-change triggers: add-to-cart success morph, like and save particle burst, expand and collapse to intrinsic height with calc-size(), swipe-to-dismiss on Pointer Events, and skeleton-to-loaded crossfade. Data-driven triggers: count-up KPI metrics, SVG sparkline draw-on-enter, and progress ring fill on load. Ambient idle loops: breathing glow, floating drift, animated gradient mesh backgrounds, conic rotating borders, auto-cycling testimonial decks, and live status pulses. Plus four hover patterns where the effect is the topic itself: cursor spotlight, holographic foil glare, corner ribbon slide, and horizontal accordion expand. Every card is scoped under a .ac-NN prefix for no-collision pasting, guards prefers-reduced-motion, animates compositor-only properties, and ports unchanged to React, Vue, Svelte, Astro, Next.js and Tailwind.

22 CSS Avatars preview

22 CSS Avatars

22 hand-coded CSS avatars for chat apps, team dashboards, comment threads, account menus, and social profiles. Covers circular and squircle shapes, gradient and conic story rings, hexagon clip-path crops, online status dots, notification count badges, verified checkmarks, stacked facepiles with plus-N overflow, initials fallbacks for users without photos, broken-image recovery, avatar pickers, and a size scale system where the ring, badge, and status dot all scale from a single custom property.

25 CSS Button Groups preview

25 CSS Button Groups

25 hand-coded CSS button groups: segmented controls, split buttons, pill radios, toggle groups, filter chips, floating action buttons, pricing toggles, Web3 wallet-connect grids, AI model pickers, icon toolbars — with Popover API, offset-path, View Transitions, @property, :has(), and every modern CSS primitive. Zero dependencies vs Radix/shadcn/Aceternity, WCAG 2.2 AA accessible, MIT licensed.

Search CodeFronts

Loading…