Puneet Sharma - Frontend Developer & UI Engineer
Puneet Sharma
Frontend Dev & UI Engineer · 16+ yrs · pixel-perfect HTML, React & WordPress

10 Copy-Paste Card Snippets: 3D Flips, Holographic Glare, Motion-Path Borders & Container Queries

10 free copy-paste card snippets with live previews — 3D flip, holographic glare, motion-path border, focus grid, spring expand, container queries.
10 Copy-Paste Card Snippets: 3D Flips, Holographic Glare, Motion-Path Borders & Container Queries

A card is the most boring component in any design system and the one you ship the most of. It's a box with a border radius. Which is exactly why the interesting question isn't what a card looks like sitting still — it's what happens when someone points at it. A card that tilts toward the cursor, dims its neighbours, catches the light, or grows into a full detail view is doing the same job as the flat box next to it, but it tells the user the thing is interactive before they've clicked anything.

Below are ten free, self-contained card snippets, each built around a different mechanism rather than a different colour scheme: a pure-CSS 3D flip, an animated gradient border, a light bead that follows the border's actual corner radius via CSS Motion Path, a grid that blurs every card except the one you're on, an overlay that enters from the exact edge your cursor crossed, a holographic foil that reacts through blend modes, a parallax card with real per-layer depth, a swipeable deck, a card that expands into a detail panel on a spring, and one that rewrites its own layout based on how wide its container is. Every one is a live, interactive preview — hover, tap and drag them right here in the article — and each exports to React, Vue, Angular or Tailwind in one click from its snippet page. Eight of the ten are plain HTML, CSS and vanilla JavaScript with no dependencies at all; the two that use a library (both around 4kb, from a CDN) are flagged where they appear, because in both cases the library is doing something CSS genuinely can't.

What these ten get right

  • The effect is driven by one number, not a pile of state. A pointer position normalised to 0–1, a data-pos index, a depth offset attribute, a container width. Each card reads one value and derives everything else from it, which is why they're all short enough to actually read.
  • CSS does the animating wherever it can. Several of these have JavaScript that never animates anything — it sets a custom property or toggles a class and lets the transition run. That's what keeps them smooth on a mid-range phone.
  • Blend modes and depth over opacity and drop shadows. The glare and foil layers compute their colour from what's underneath them, and the 3D cards separate their layers along Z. Both are the difference between "gradient pasted on top" and something that reads as a physical surface.
  • Hover isn't the only input. Touch has no hover and keyboards have no cursor. The focus-cards grid wires the same effect to :focus-within and a tap handler; the deck takes pointer swipes; the flip and expand cards are click-driven. None of them are dead on a phone.
  • The content stays readable through the animation. The expand card animates width and height rather than scale() specifically to avoid squashing its own text, and the 3D cards push their copy forward with translateZ so it stays flat to the viewer. The effect serves the content rather than mangling it.

1. 3D Flip Card

Click the card and it rotates in 3D to reveal a completely different back face — front for the summary, back for the detail. Hovering adds a small tilt in either state.

How it works: four CSS properties carry the whole effect, and there is essentially no JavaScript — the trigger is onclick="this.classList.toggle('flipped')" inline in the markup. The stage sets perspective: 1000px, which is what gives the rotation a vanishing point instead of looking like a flat squash. The card gets transform-style: preserve-3d so its two faces keep their own positions in 3D rather than being flattened into the parent's plane. Each face gets backface-visibility: hidden, which hides a face once it has rotated more than 90° away from you. The trick that ties it together: the back face is pre-rotated to rotateY(180deg) at rest, so it's facing away and invisible. When .flipped rotates the card 180°, the front swings away and is hidden, while the back lands at an effective 0° facing the viewer. Remove either preserve-3d or backface-visibility and the illusion collapses — you'd see both faces at once, one mirrored.

Best for: flashcards, team cards with a bio on the back, and feature tiles where two screens of content need to share one slot. Tip: the flipped hover state uses rotateY(172deg) — 180 minus the 8° hover tilt — so the tilt leans the same way whichever face is showing. Copy that offset trick any time you layer a hover state on top of a transformed base state.

Grab the code: 3D Flip Card

2. Gradient Border Card

A card wrapped in a 1.5px border that cycles smoothly through indigo, violet and pink — the look every AI and crypto product landing page has converged on.

How it works: CSS has no way to put a gradient on a border directly with a border radius intact, so this fakes it with a pseudo-element. .card::before sits at inset: -1.5px — extending slightly past the card on all four sides — with border-radius: 19px against the card's 18px so the corners nest correctly, and z-index: -1 to put it behind the card's own opaque background. The result is that only the 1.5px strip around the edge is ever visible. The animation is the standard oversized-gradient trick: the background is a linear-gradient at background-size: 300% 300%, and a keyframe slides background-position from 0% 50% to 100% 50% and back over four seconds, so the colours travel around the edge without anything actually moving. overflow: hidden on the card isn't optional — without it the pseudo-element's overhang bleeds past the rounded corners.

Best for: highlighting one plan in a pricing grid, a "featured" card, or any panel that needs to look premium without a redesign. Tip: the modern upgrade is registering an angle with @property --angle { syntax: '<angle>' } and animating a conic-gradient around it — that gives you a true rotating sweep rather than a panning linear gradient, and it interpolates smoothly because the browser now knows the custom property is an angle rather than a string.

Grab the code: Gradient Border Card

3. Border Beam

A bright bead of light that travels continuously around the card's border, banking through the rounded corners like a comet on a track. Two beams chase each other in opposite phases.

How it works: this is the one that's worth reading even if you never use the effect, because it's built on CSS Motion Path — an API most people still haven't touched. The beam is a 90px gradient pill, and its entire path is one declaration: offset-path: rect(0 100% 100% 0 round 18px) defines a rounded-rectangle track matching the border, animating offset-distance from 0% to 100% walks the pill around it, and offset-rotate: auto keeps it oriented along its direction of travel so it banks into the corners instead of sliding sideways through them. No SVG path, no per-frame JavaScript, and the browser composites it on the GPU. The comet look comes from the pill being elongated with a transparent-to-bright gradient plus a coloured drop-shadow, and the second beam is the same element with a different hue and a -2s animation delay. The card uses overflow: hidden and isolation: isolate so the glow is clipped to the shape and the stacking context stays self-contained. There's a JavaScript fallback that walks the perimeter manually, but it's gated behind CSS.supports('offset-path', …) and most visitors never run it.

Best for: drawing the eye to a single card, a CTA panel, or an input that's waiting on the user. Tip: the older way to do this — spinning a huge conic gradient behind a masked panel — can't follow a corner radius properly and repaints a much larger area. If you have a spinning-gradient border in your codebase, offset-path is a smaller, more accurate replacement.

Grab the code: Border Beam

4. Focus Cards

Hover any card in the grid and it sharpens and lifts while every other card blurs and dims — and its caption fades in. Works from the keyboard and on touch too.

How it works: the core is two CSS rules and no JavaScript decision-making at all. When the grid is hovered, a rule blurs, darkens and slightly shrinks every card inside it. A second, more specific rule targets the card actually under the cursor and restores it to full sharpness, scales it up and raises its z-index and shadow. Because the hovered-card rule wins on specificity, the net effect is "everything dims except this one" — decided entirely by the cascade, which is why there's no active-index state to keep in sync. Captions ride along: they sit at opacity: 0 with a small downward offset by default and only transition in on the focused card, so the grid stays clean at rest. The accessibility work is the part worth copying: every card carries tabindex="0", the dimming rules also fire on :focus-within, and the active styles apply on :focus-visible, so tabbing through produces the identical effect. A small script covers touch by calling focus() on tap — which triggers those same rules — with Escape and a tap on empty space to reset.

Best for: galleries, team pages, and feature grids where you want attention on one item at a time. Tip: blur(2px) and brightness(.6) are the two dials. Blur is expensive on large images across many elements — if a big grid stutters on mobile, drop the blur and keep the brightness and scale change; you lose surprisingly little of the effect.

Grab the code: Focus Cards

5. Direction-Aware Hover

The caption overlay slides in from the exact edge your cursor crossed — enter from the left and it comes from the left, leave through the bottom and it exits downward.

How it works: the interesting part is how cheaply the entry edge is detected. On pointerenter, the handler converts the cursor's position relative to the card's centre into −0.5…0.5 fractions on each axis and asks one question: which magnitude is larger? If the horizontal offset dominates, the pointer came from the left or right; otherwise top or bottom, with the sign choosing the specific side. That dominant-axis test classifies entry into four directions with no trigonometry. The result is written into two custom properties, --tx and --ty, which park the overlay just outside the matching edge; the CSS then transitions translate(var(--tx), var(--ty)) to translate(0, 0) when a .show class is added. One detail makes it work at all: .show is added inside a requestAnimationFrame callback, because the browser needs one frame to register the overlay at its off-screen start before the transition target is applied — set both in the same tick and it jumps straight to visible with no animation. On pointerleave the class is removed and the edge is recomputed from the exit point, so the overlay retreats toward whichever side you actually left by.

Best for: portfolio and image galleries, category tiles, anything with a caption that shouldn't be on screen permanently. Tip: the direction logic doesn't care what it's attached to. Lift the edge() function and the two custom properties and you can point them at menus, tooltips or drawer panels.

Grab the code: Direction-Aware Hover

6. Glare Card

A holographic collectible: it tilts toward your pointer while a bright glare hotspot tracks under the cursor and a rainbow foil sheen flows across the surface.

How it works: one pointermove handler drives three separate effects, and the reason it convinces is that two of them are blend modes rather than overlays. The tilt is the familiar part — cursor position converted to 0–1 fractions, mapped to rotateX and rotateY of up to about 14° each, with the vertical axis inverted so the card tips toward the pointer, and a deliberately short .12s transition that smooths the motion without lagging behind the cursor. The glare is a radial gradient whose centre is set by two custom properties, --mx and --my, updated from that same handler, and it uses mix-blend-mode: soft-light so it brightens the colours underneath instead of painting an opaque white blob. The foil is a conic-gradient at background-size: 200% whose background-position pans with the pointer, set to mix-blend-mode: color-dodge — that's what produces the iridescent metallic shimmer against the dark card rather than a flat rainbow wash. Finally, the card body is pushed forward with translateZ(40px) inside the preserve-3d context, so the text parallaxes above the surface effects as the card tilts.

Best for: collectibles and NFT cards, membership and loyalty cards, event tickets, and a premium tier in a pricing grid. Tip: blend modes are the whole lesson here. soft-light and color-dodge derive their output from the layer beneath, so the same glare reads differently over a dark navy card than over white — which is exactly how real reflections behave, and why swapping either one for plain opacity instantly makes it look like a sticker.

Grab the code: Glare Card

7. Atropos 3D Parallax Card

A tilt card where every layer moves by a different amount — the badge travels furthest, the background drifts the opposite way — so the card reads as an object with real depth rather than a picture on a hinge.

How it works: this is one of the two snippets here that loads a library — Atropos, about 4kb from a CDN — and it earns it, because differential motion between layers is the cue your visual system actually uses to infer depth, and hand-rolling it per element is tedious. The structure is mandatory rather than stylistic: .atropos > .atropos-scale > .atropos-rotate > .atropos-inner, with each level owning exactly one transform. Combine the scale and the rotation onto a single element and they multiply into a visible skew as they animate; splitting them keeps each independent. From there the entire depth design is one attribute per child — data-atropos-offset — holding a plain number: -6 on the background gradient, -3 on the glow, 2 and 4 on the kicker and copy, 9 on the product orb, 14 on the corner badge. Negative values move against the pointer, and that opposing motion between backdrop and foreground does more for perceived depth than anything else in the file. Read top to bottom, those numbers are the card's z-order, and adjusting depth means editing one attribute — no CSS, no JavaScript.

Best for: a product hero, a feature card that needs to stop the scroll, anywhere a flat tilt already looks dated. Tip: two restraint settings matter more than the offsets. rotateXMax/rotateYMax are set to 14° where tilt scripts commonly default to 25 or more — past that, text along the far edge visibly smears. And push activeOffset too high and the whole card reads as a zoom, swallowing the per-layer parallax that's meant to be doing the work. Keep individual offsets inside roughly ±20 or layers start to visibly detach from the card edges.

Grab the code: Atropos 3D Parallax Card

8. Stacked Cards Deck

A five-card deck with real physical stacking — swipe or use the arrows to send the top card flying off to the left and promote the one beneath it.

How it works: the JavaScript here never animates anything — it only ever writes a number. Each card carries a data-pos attribute from 0 to 4, and five CSS rules define what each depth looks like: position 0 sits at translateY(0) scale(1) at full opacity, and each layer behind it steps down by 10px of Y offset, 3% of scale and a chunk of opacity, ending at translateY(40px) scale(0.88) at 0.2. When you advance, the script recalculates data-pos on every card and the browser interpolates between the old and new rules through transition: transform .45s cubic-bezier(.34,1.56,.64,1). That easing curve has control points beyond 1, which produces a slight overshoot — the deck settles with a small bounce instead of arriving dead, and that's most of why it feels physical. Dismissal is a separate .exit-left class that translates the top card off-screen with a −8° rotation and a fade, then a 380ms timeout — deliberately just inside the 400ms transition — strips the class, increments the index and re-stacks the deck, so the departed card silently reappears at the bottom. Swipes come from pointer events, and the prev/next buttons drive the same code path. Zero dependencies.

Best for: onboarding sequences, flashcards, recommendation feeds, and any Tinder-style "one decision at a time" flow. Tip: the two numbers that define the whole look are the per-layer Y offset and the per-layer scale step. Widen the offset for a fanned-out deck, tighten both for a thick single-block stack.

Grab the code: Stacked Cards Deck

9. Motion One Spring Card Expand

Click a card in the grid and it grows into a centred detail panel on a spring, then flies back into its exact slot when closed — the App Store transition, without React.

How it works: this is the shared-element transition people usually assume requires Framer Motion's layoutId, done in plain JavaScript with Motion One (~4kb, the second and last library in this set) for two things CSS can't provide: a real spring() easing and a promise that resolves when the animation settles. The spring is { stiffness: 210, damping: 24, mass: 1 } — a physical system rather than a curve, with no duration, so the physics decides when it's done and the open and close feel consistent despite covering different distances. The tiny overshoot at that damping ratio is what the eye reads as weight. Two implementation details are worth stealing. First, it follows FLIP discipline: getBoundingClientRect() captures the card's real position before anything changes, and those values are written straight back as explicit top/left/width/height, so the instant the card goes position: fixed nothing appears to move. Second — the part most implementations miss — an empty placeholder div of exactly the card's measured size is inserted into the grid before the card is lifted out of flow, so the siblings never jump; on close, the animation targets the placeholder's current rect, meaning the card returns to the right slot even if the window was resized mid-transition. Closing waits on anim.finished and then strips the entire inline style attribute in one call, so no stale position: fixed survives into the next open.

Best for: product and article grids, media libraries, any list-to-detail navigation that shouldn't feel like a page load. Tip: note that it animates width and height rather than transform: scale(). Scale is cheaper, but non-uniform scaling distorts the text inside the card — the squashed-headline artifact — and fixing that means counter-scaling every child. For one element, animating layout properties keeps the type crisp and costs nothing you'll notice.

Grab the code: Motion One Spring Card Expand

10. Container Query Card

One card, one set of markup, three genuinely different layouts — decided by the width of its container rather than the width of the window. Drag the handle and watch the breakpoints fire.

How it works: this is the least flashy snippet here and the one most likely to change how you build cards. Media queries ask how wide the viewport is — but components live in sidebars, grid cells and modals, and a card doesn't know or care what the window is doing. Two declarations fix that: container-type: inline-size makes the wrapper a query container measured on its inline axis, and container-name: card lets queries target it specifically rather than the nearest ancestor container, which becomes essential the moment components nest. container-type also applies size containment — the container's width can no longer be influenced by its contents — and that constraint is precisely why the feature took a decade to ship: without it, a child changing layout could resize the container and re-trigger the query forever. The card's base styles are the narrow layout (media on top, description hidden, one meta item). At @container card (min-width: 340px) it becomes a row with the art at 34%; at 480px the art grows to 40%, the meta list rotates from a column into an inline row exposing all three items, and padding and button sizing step up. Note what's changing: layout, visibility and density — the information hierarchy adapts, not just the scale. The demo drives that home by putting the identical markup in a fixed 240px column beside the resizable one, both rendering differently on the same screen with zero props, classes or JavaScript involved.

Best for: design-system components that have to survive being dropped into any slot, dashboard widgets in resizable grids, and embeddable widgets where you don't control the host page at all. Tip: pair the breakpoints with cqi units for the details — 1cqi is 1% of the container's inline size, so type and spacing scale fluidly between breakpoints instead of stepping. Between the two you rarely need more than three container breakpoints for any card.

Grab the code: Container Query Card

How to drop these into your project

  1. Open any snippet and hit View / Edit Code to see the HTML, CSS and JS in separate tabs, then paste the HTML into your markup, the CSS into your stylesheet, and the JS before your closing </body> tag — or use the one-click export to React, Vue, Angular or Tailwind right from the snippet page.
  2. Check what you're actually pulling in. Eight of these ten need nothing but the three files. The Atropos card and the spring expand card each load a ~4kb library from a CDN — fine for a prototype, but self-host or npm-install it for production so a third-party CDN outage can't take your card layout with it.
  3. Copy the mechanism, not the card. The reusable parts here are the edge() dominant-axis test, the "dim the siblings, restore the hovered one" cascade trick, the --mx/--my pointer-to-custom-property pattern, the FLIP measure-then-animate discipline, and the placeholder div that stops a grid from reflowing. All five work on components that aren't cards.
  4. Set the pointer effects up as progressive enhancement. Tilt, glare and direction-aware overlays are all hover-driven, so decide what a touch user sees before you ship: the focus-cards grid shows the right approach, wiring the same visual state to :focus-within and a tap handler rather than leaving the effect dead.
  5. Respect prefers-reduced-motion. The springs, the travelling beam and the parallax are exactly the kind of motion that causes problems for some users. A single @media (prefers-reduced-motion: reduce) block that zeroes the transforms and shortens the transitions is a few lines and makes every one of these safe to ship.
  6. Keep pointer handlers cheap. The tilt cards write a transform or a custom property on every pointermove. That's fine for one card, but if you put a dozen on a page, batch the writes into a requestAnimationFrame so you're not forcing style recalculation multiple times per frame.

Final thought

What separates these ten from a folder of gradient presets is that each one is a technique with a name — motion path, blend mode, FLIP, containment, the specificity cascade — that happens to be demonstrated on a card. Learn the technique and the card is the least interesting thing you can do with it: the same edge detection drives a menu, the same containment fixes a sidebar widget, the same spring makes any dialog feel like an object rather than a div appearing. Cards are just the most convenient place to practise.

Hover them, drag them, retune the constants, and export to your framework of choice in one click. Browse the full collection at FWD Tools UI Snippets — it's free and runs entirely in your browser.

About the author

Puneet Sharma
Puneet Sharma is a freelance web developer and the creator of FWD Tools and WebDevPuneet. Follow him on X/Twitter

Post a Comment