24 hand-coded CSS animated cards grouped by what triggers the motion — scroll entrances, mount-in reveals, click state changes, data arrival, and ambient idle loops. Covers staggered reveals, @starting-style mounts, View Transitions detail morphs, FLIP filter re-layout, add-to-cart morphs, count-up KPIs, and conic gradient borders. For pointer-driven card motion see card hover effects, 3D tilt and stacked cards. Scoped under .ac-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.

13 pure CSS11 light JSPublished

Related33 CSS Card Hover Effects15 CSS 3D Tilt Hover Cards36 CSS Stacked Cards20 CSS Cards

Staggered Grid Entrance Reveal — preview
01 / 24Pure CSS

Staggered Grid Entrance Reveal

The cascade every editorial and product grid opens with — cards fading and lifting into place 90 ms apart so the page reads as choreographed rather than dumped. Built with a single keyframe and one custom property for the index, plus a pure-CSS replay switch that restarts the whole cascade by swapping the animation name — no JavaScript anywhere. Includes the 2026 one-liner (sibling-index()) alongside the universal nth-child fallback.

Published

@starting-style CSS Mount-In Animation — preview
02 / 24Light JS

@starting-style CSS Mount-In Animation

Cards that animate in the moment they are inserted into the DOM and animate out before they are removed — the behaviour that used to require Framer Motion or a double requestAnimationFrame hack. @starting-style defines the pre-mount state, transition-behavior: allow-discrete lets display and overlay participate in the transition, and the JS is reduced to appendChild and remove.

Published

Scroll-Driven Scale + Fade — preview
03 / 24Pure CSS

Scroll-Driven Scale + Fade

Cards whose scale, opacity and blur are a direct function of scroll position — scrubbed by the browser off the main thread, so it never janks. Uses animation-timeline: view() with a hand-tuned animation-range so cards settle exactly when they become comfortably readable, plus a scroll() driven progress rail at the top. The panel scrolls itself, so the demo works inside any playground.

Published

View Transitions Card-to-Detail Morph — preview
04 / 24Light JS

View Transitions Card-to-Detail Morph

Tap a card and it becomes the detail view — the thumbnail grows into the hero, the title slides into the headline, the whole thing morphs instead of cutting. This is the shared-element transition that native apps have had for a decade, now three lines of web platform: give the paired elements the same view-transition-name and wrap the DOM change in document.startViewTransition().

Published

Blur-to-Sharp Lazy Image Card — preview
05 / 24Light JS

Blur-to-Sharp Lazy Image Card

The blur-up every image-heavy card grid should ship: a tiny gradient or LQIP renders instantly, the real photo decodes off-thread, then unblurs and settles into place. Zero layout shift because the aspect-ratio is reserved up front, and the whole reveal is four CSS declarations plus img.decode(). Press Reload images to watch it again with a simulated slow connection.

Published

Filter Re-Layout with FLIP — preview
06 / 24Light JS

Filter Re-Layout with FLIP

Filter a grid by category and the surviving cards travel to their new positions instead of teleporting. This is FLIP — First, Last, Invert, Play — thirty lines of vanilla JS using getBoundingClientRect and the Web Animations API, the technique behind every polished layout transition. Includes the View Transitions one-liner alternative for browsers that have it.

Published

Add-to-Cart Success Morph — preview
07 / 24Light JS

Add-to-Cart Success Morph

The three-state commerce button done properly: idle → pending → confirmed, with the label collapsing into a spinner and the spinner blooming into a drawn checkmark, then the cart badge counting up. One button element throughout, so focus is never lost and assistive tech follows the state change instead of a disappearing node.

Published

Like/Save Burst Micro-Interaction — preview
08 / 24Light JS

Like/Save Burst Micro-Interaction

The like that feels good to press: an overshooting heart, twelve particles thrown out on trigonometric angles, an expanding ring, and a count that rolls over — all CSS keyframes fired by a single class toggle. The particles are pure CSS (no canvas, no library), positioned with a rotate-then-translate trick so twelve elements need one keyframe between them.

Published

CSS Expand Collapse Card (Pure CSS Height Auto) — preview
09 / 24Pure CSS

CSS Expand Collapse Card (Pure CSS Height Auto)

Animating to height: auto — the oldest impossible thing in CSS — solved twice over. The modern route is one line, interpolate-size: allow-keywords, which makes intrinsic keywords animatable. The universal route is the grid-template-rows: 0fr → 1fr trick. Both are wired to real <details> elements, so keyboard, screen reader and find-in-page all work with zero JavaScript.

Published

Swipe-to-Dismiss Card — preview
10 / 24Light JS

Swipe-to-Dismiss Card

Notification cards you can throw off screen — with a rubber-band resist before the threshold, colour-coded action reveals behind the card, and momentum-aware release. Built on Pointer Events (one code path for mouse, touch and pen), with touch-action keeping vertical scroll native. Every gesture has a keyboard equivalent, because a swipe-only affordance is an accessibility failure.

Published

Skeleton-to-Loaded Crossfade — preview
11 / 24Light JS

Skeleton-to-Loaded Crossfade

A skeleton that actually helps: same geometry as the real card, a shimmer that sweeps at reading speed, and a crossfade so content arrives instead of snapping. The shimmer is one animated background-position — no pseudo-element pyramid — and the whole card is marked aria-busy so assistive tech waits quietly instead of reading placeholder rectangles.

Published

Count-Up KPI Metrics Card — preview
12 / 24Pure CSS

Count-Up KPI Metrics Card

Dashboard KPI tiles whose numbers genuinely interpolate — no JavaScript, no requestAnimationFrame loop. A registered @property integer is animated by the style engine and printed through counter(), the delta chips slide in behind it, and the whole row cascades. This is the pure-CSS counter every analytics card should be using in 2026.

Published

Sparkline Draw-On-Enter — preview
13 / 24Pure CSS

Sparkline Draw-On-Enter

An analytics card whose trendline draws itself, its area fill wipes in behind, and its end-point dot lands last — the classic SVG line-draw, but with the pathLength trick that removes the getTotalLength() measuring step entirely. Pure CSS, three coordinated animations, and a live crosshair on hover.

Published

Progress Ring Fill on Load — preview
14 / 24Pure CSS

Progress Ring Fill on Load

Circular progress done two ways, side by side: a conic-gradient ring animated with a registered @property angle (no SVG at all), and the classic SVG stroke-dasharray arc. Both fill on load with an ease that decelerates into the target, both carry role="meter" with real values, and both re-theme from a single hue token.

Published

Ambient Breathing Glow — preview
15 / 24Pure CSS

Ambient Breathing Glow

The featured-plan card that genuinely breathes. Two counter-phased auras swell and fade on different periods so the light never looks like a single lamp switching on and off; a conic halo travels around the panel edge; a registered hue property sweeps the whole palette 46 degrees, violet through magenta and back; the rim, the crown, the badge and the feature pips all pulse on the same 6-second clock at staggered phases. Everything animated is composited — opacity, scale and one custom property — and a veil layer keeps the copy at full contrast on the brightest frame.

Published

Floating Drift Idle — preview
16 / 24Pure CSS

Floating Drift Idle

A hero card that levitates: three layers drifting on different periods so the motion never visibly loops, a shadow that tightens as the card rises, and a hover that lifts it out of the cycle without a jump. The trick is prime-ish durations (7 s, 9 s, 11 s) — their combined cycle is long enough that the eye never catches the repeat.

Published

Animated Gradient Mesh Background — preview
17 / 24Pure CSS

Animated Gradient Mesh Background

A fluid mesh gradient built from four blurred radial blobs drifting on independent orbits — the aurora backdrop every modern dark-mode card wants, with no SVG filters, no canvas and no images. Animating transforms on small blurred layers keeps it cheap; animating background-position on a giant gradient (the usual recipe) does not.

Published

Animated Gradient Border Card (Conic Rotate) — preview
18 / 24Pure CSS

Animated Gradient Border Card (Conic Rotate)

The rotating neon outline, done three ways so you can pick your compatibility floor: a registered @property angle sweeping a conic gradient, a mask-composite ring that keeps the card background transparent, and a padding-box fallback. Includes the glow-bloom variant where a blurred copy of the border sits behind the card.

Published

Auto-Cycling Testimonial Deck — preview
19 / 24Light JS

Auto-Cycling Testimonial Deck

Testimonials in a physical stack: the front card slides away and drops to the back while the rest step forward, on a 6-second loop that pauses on hover, on focus, and whenever the tab is hidden. Depth comes from one transform per position (translateY + scale + a whisper of rotation) driven by a single --i variable, so any number of cards works with no extra CSS.

Published

Live Status Pulse Card — preview
20 / 24Pure CSS

Live Status Pulse Card

The online dot, engineered: concentric rings expanding on a staggered 2.4-second loop, a core that brightens on the same clock, and status colour driven entirely by one data attribute so operational/degraded/down are a single-token swap. Includes the uptime bar with per-day tooltips that every status page needs.

Published

Mouse Cursor Spotlight Card Hover Effect — preview
21 / 24Light JS

Mouse Cursor Spotlight Card Hover Effect

Not six independent hover states — one light. A single source with inertia drifts toward your cursor, and every card computes its own distance and direction from it: brightness falls off with the square of distance, text lightens as the light approaches, icon tiles cast shadows away from it, and a specular dot slides across each tile toward it. The grid keeps breathing when you leave (the light drifts on a Lissajous path), keyboard focus walks the light to the focused card, and reduced motion parks it dead centre with no loop at all.

Published

Holographic Glare / Foil Shine — preview
22 / 24Light JS

Holographic Glare / Foil Shine

The collectible-card effect: the card tilts toward the cursor, a rainbow foil layer shifts hue with the angle, a specular highlight tracks the pointer, and a hard glare sweeps across on entry. Three stacked blend layers over a real 3D transform — and a CSS-only sweep for touch devices where there is no pointer to follow.

Published

Corner Ribbon Slide Animation — preview
23 / 24Pure CSS

Corner Ribbon Slide Animation

Corner ribbons that arrive instead of just existing: a diagonal banner sliding out of the card corner on load, folded end-tabs cut with clip-path, and a hover wiggle with a light sweep running along the fabric. Pure CSS, no images, and the ribbon text stays readable to screen readers rather than being baked into a background.

Published

Horizontal Accordion Expand — preview
24 / 24Pure CSS

Horizontal Accordion Expand

The image accordion: hover or focus a panel and it expands while its neighbours shrink, with captions rotating upright as their panel opens. Built on :has() and animatable grid-template-columns, so the whole interaction is declarative CSS — and it is fully keyboard-operable, which almost no version of this effect on the web is.

Published

FAQ

Frequently asked questions

What is the difference between this collection and CSS card hover effects?
This collection is organised by what triggers the animation, not by what the card looks like. That distinction matters because the two answer different questions. If the motion should fire when the pointer arrives, you want hover effects — tilt, glow, image zoom, flip — and those are covered in depth in our CSS card hover effects collection, which ships 33 patterns. This collection covers everything that animates without a pointer: entrances that fire when the card scrolls into view, mount animations when the element is inserted into the DOM, state changes when a user clicks add-to-cart or like, data-driven motion when a number arrives, and ambient loops that run continuously. In practice a production card often uses both — a staggered entrance from here, a hover lift from there — and because every demo is scoped under its own .ac-NN prefix, you can paste one of each onto the same page with no collisions. Four hover patterns are included here anyway (cursor spotlight, holographic foil, corner ribbon, horizontal accordion) because in those four the effect is the topic people search for, not an incidental hover state.
How do I animate cards as they scroll into view without a library?
Two approaches, and the right one depends on how much browser support you need. The modern CSS-only path is animation-timeline: view(), which binds a keyframe animation to an element's position within the viewport rather than to wall-clock time: .card { animation: rise linear both; animation-timeline: view(); animation-range: entry 0% cover 30%; }. The animation runs off the main thread, so a long grid stays smooth even while JavaScript is busy. animation-range is what makes it feel right — entry 0% cover 30% means the animation starts as the card's top edge enters the viewport and finishes when it has covered 30 percent of it. The portable path is IntersectionObserver: observe each card, add a class on isIntersecting, and unobserve immediately so it fires once rather than every time the user scrolls back. Add rootMargin: '0px 0px -10% 0px' so the animation triggers slightly before the card is fully visible. For staggering, do not schedule timers — set animation-delay: calc(var(--i) * 60ms) from an index custom property, so the browser handles the sequencing. Keep total stagger under roughly 400ms or the last card feels broken rather than choreographed. Demos 01 and 03 implement both paths.
How do I animate a card expanding to its natural height?
This was the long-standing gap in CSS: height: auto could not be transitioned, so the workaround was animating max-height to a guessed value — which either clips tall content or eases at visibly the wrong speed because the transition is running across a range the content never uses. Two modern primitives fix it properly. interpolate-size: allow-keywords, set once on :root, makes intrinsic size keywords animatable everywhere, so a plain transition: height .3s to height: auto simply works. Or use calc-size(auto) directly on the target when you want it opt-in per component rather than global. Where neither is supported, the robust fallback is a CSS Grid trick rather than max-height: wrap the content in a container that transitions grid-template-rows from 0fr to 1fr, with the inner element set to overflow: hidden. That animates to true content height with no magic numbers and no measurement JavaScript. Whichever you use, the toggle should be a real <button> carrying aria-expanded, or a native <details> element which brings its own disclosure semantics. Demo 09 ships the pure-CSS version with the grid fallback.
How does the View Transitions API animate a card into a detail page?
The View Transitions API handles the hardest part of a card-to-detail animation: making an element appear to persist across a DOM change or a navigation. You give the card and the detail-page hero the same view-transition-name, and the browser captures before and after snapshots and interpolates between them — position, size, and border radius all morph automatically. For a same-page change, wrap the DOM update: document.startViewTransition(() => { updateTheDOM() }). For cross-document navigation, opt in with @view-transition { navigation: auto; } in CSS on both pages. Two rules people trip on. First, view-transition-name must be unique per transition — if a grid of twelve cards all share one name the browser bails out entirely, so assign the name only to the card being activated and remove it afterward. Second, the API degrades to an instant swap where unsupported, so gate any transition-specific styling behind @supports (view-transition-name: none) and never make the navigation itself depend on the animation completing. Astro's built-in view transitions and Next.js App Router both build on this same primitive. Demo 04 is the reference implementation.
How do I animate a card grid when a filter changes?
Filtering a grid by adding and removing cards causes the survivors to jump to new positions instantly, which reads as a glitch rather than a change. The fix is the FLIP technique — First, Last, Invert, Play. Measure each card's position before the change with getBoundingClientRect(). Apply the DOM change. Measure again. Then apply a transform that moves each card back to where it started, and immediately transition that transform to zero, so the browser animates from old position to new using only compositor-friendly transforms rather than animating layout properties. The whole implementation is roughly 30 lines and it is what Isotope, Muuri and Framer Motion's layout animations all do internally. Two production details: read all the positions before writing any styles, so you do not trigger repeated layout recalculation inside the loop; and cap the animation around 300ms, because layout animations feel sluggish much faster than opacity animations do. For cards entering or leaving rather than moving, pair FLIP with @starting-style for the entry and a discrete-transition exit. Demo 06 implements this, and Demo 02 covers the entry case on its own.
Do these animations hurt Core Web Vitals or accessibility?
Not if they are built the way these are, and both concerns are addressed structurally rather than as an afterthought. Every demo animates compositor-only properties — transform, opacity, filter, and registered custom properties — never width, height, top or left on the hot path, so animation work stays off the main thread and out of layout. Cumulative Layout Shift stays at zero because entrance animations move elements with transforms while their layout box is already reserved; nothing reflows. Interaction to Next Paint stays safe because every JavaScript handler is rAF-coalesced and scroll and pointer listeners are registered { passive: true }. On accessibility, all 24 demos honour prefers-reduced-motion: reduce — and importantly they degrade to the finished state rather than to nothing, so a user who has requested less motion still sees the content, just without the movement. Interactive controls are real <button> elements with visible :focus-visible rings at 2px minimum and 3:1 contrast, and hit targets of at least 44 by 44 CSS pixels. Auto-cycling content pauses on hover and on :focus-within, which WCAG 2.2.2 requires for anything that moves for more than five seconds.
How much JavaScript do these need, and can I drop my animation library?
Thirteen of the 24 demos are pure CSS with no JavaScript at all — every ambient loop, the count-up, the sparkline draw, the progress ring, the conic border, the ribbon and the horizontal accordion. The other eleven need JavaScript because the trigger genuinely lives there: IntersectionObserver for scroll entrances, pointer events for swipe, startViewTransition for the navigation morph, position measurement for FLIP. Those range from about 12 to 40 lines each, dependency-free, written as self-contained init functions. For comparison, the libraries usually reached for here are considerably heavier: Framer Motion is roughly 40KB gzipped and requires React, GSAP with ScrollTrigger around 70KB, AOS about 14KB, and Isotope roughly 34KB plus jQuery in older setups. If you are pulling in a full animation library purely for scroll-triggered card entrances, animation-timeline: view() or a 15-line IntersectionObserver replaces it outright. Where libraries still earn their weight is orchestrated timelines, physics-based springs, and complex interruptible sequences — none of which these patterns need.
How do these port to React, Vue, Svelte, Next.js and Tailwind?
The CSS ports unchanged — every .ac-NN selector, @property registration and keyframe is framework-agnostic, and the 13 pure-CSS demos need no porting work at all. For the 11 with JavaScript, the work is lifecycle placement. React: useEffect(() => { const cleanup = init(); return cleanup }, []) — register once on mount, tear down on unmount, and never re-register per render, which is the most common bug when porting scroll observers. Vue 3: onMounted plus onBeforeUnmount. Svelte: onMount(() => { init(); return cleanup }). Next.js App Router: the interactive demos need 'use client' since they touch browser APIs; the 13 pure-CSS ones render fine as server components. Astro: client:visible suits card grids well, since they are usually below the fold — and Astro's own view transitions build on the same API as Demo 04. For Tailwind v4, layout and spacing translate to utilities directly, while the parts with no utility equivalent — @property registrations, keyframes, animation-timeline, animation-range — belong in a @theme block. Each demo is 2 to 6KB of CSS cherry-picked.

Search CodeFronts

Loading…