22 CSS Transition Effects

A CSS transition is the smooth animated change between two states — the most-used motion primitive on the web in 2026. These 22 hand-coded transition effects cover every production pattern: button hover, scroll-reveal, flip cards, text reveal, image zoom, modal open/close, page transitions, ripple, magnetic hover, 3D card tilt, glassmorphism, staggered lists, cursor trails, progress bars, and more. All GPU-accelerated (transform + opacity only — no layout thrashing, 60fps on mid-tier mobile), respect prefers-reduced-motion, and ship MIT-licensed. Drop into any stack: React, Vue, Svelte, Astro, Rails, plain HTML — no framework dependencies.

22 unique transition effects 9 Pure CSS 13 CSS + JS 100% copy-paste ready Published
01 / 22
Button Hover Transitions
Pure CSS
Button Hover Transitions — preview
Nine polished button hover effects: fill sweep, slide-up, neon glow, rotate icon, border draw, 3D depth, ripple ring, shimmer and split wipe.
02 / 22
Slide-In Animation on Scroll
CSS + JS
Slide-In Animation on Scroll — preview
Intersection Observer scroll reveal with six directions — left, right, bottom, top, scale-up and rotate-in — plus stagger delay classes.
03 / 22
Flip Card 3D Transition
Pure CSS
Flip Card 3D Transition — preview
Six 3D flip cards using rotateY and rotateX variants with unique dark gradients, perspective depth and backface-visibility control.
04 / 22
Text Reveal Animation
Pure CSS
Text Reveal Animation — preview
Clip-path translateY hero reveal, wipe-over hover on list rows, shimmer sweep on cards and animated grain background texture.
05 / 22
Image Zoom Hover Transition
Pure CSS
Image Zoom Hover Transition — preview
Nine zoom techniques: standard, rotate-and-zoom, zoom-out, colour overlay, Ken Burns pan, 3D tilt, blur-on-zoom, desaturate and clip-path inset.
06 / 22
Background Color Transition
Pure CSS
Background Color Transition — preview
Eight background-color techniques: smooth swap, gradient shift, left-to-right sweep, top-to-bottom fill, radial burst, diagonal shimmer, colour cycle and pricing card.
07 / 22
Border Animation Transition
Pure CSS
Border Animation Transition — preview
Eight border effects: clockwise draw, glow pulse, rotating gradient border, corner expand, width pulse, dashed-to-solid, colour shift, double ring plus input focus states.
08 / 22
Fade In Fade Out Transition
CSS + JS
Fade In Fade Out Transition — preview
Aurora hero, card crossfade overlays, JS-driven fade tabs with four panels and staggered notification stack with opacity transitions.
09 / 22
Navigation Hover Transition
Pure CSS
Navigation Hover Transition — preview
Five navigation styles: sliding pill, underline slide, diagonal wipe, translateX sidebar and mega dropdown reveal with smooth transitions.
10 / 22
Loading Skeleton Transition
CSS + JS
Loading Skeleton Transition — preview
Shimmer, wave and pulse skeleton variants with toggle to reveal loaded content across card grid and data table layouts.
11 / 22
Modal Open Close Transition
CSS + JS
Modal Open Close Transition — preview
Six modal entrance animations: scale-in, slide-up, flip-in, bounce overshoot, slide-right and unfold, with backdrop-filter blur overlay.
12 / 22
Page Transition Effect
CSS + JS
Page Transition Effect — preview
Four pages with four transition types each: horizontal wipe, curtain, circle burst and vertical-slices stagger — with type selector and dot nav.
Advertisement
13 / 22
Ripple Effect on Click
CSS + JS
Ripple Effect on Click — preview
Material Design ripple: JS inserts a wave span at click coordinates with contained, outlined and text buttons, FABs, chips, list items and cards.
14 / 22
Underline Animation Hover
Pure CSS
Underline Animation Hover — preview
Ten underline variants: left-grow, center-out, RTL, thick bar, double line, fill-from-bottom, dot fade, strikethrough, rainbow gradient and fade-up.
15 / 22
Number Counter Animation
CSS + JS
Number Counter Animation — preview
Stat grid counters animating on load, live odometer incrementing every three seconds and SVG circular progress rings with stroke-dashoffset transition.
16 / 22
Card Tilt 3D Hover
CSS + JS
Card Tilt 3D Hover — preview
Four cards with CSS custom property glare driven by --gx/--gy, floating gradient orbs with parallax offset, JS mousemove rotating up to 18 degrees.
17 / 22
Glassmorphism Hover Transition
Pure CSS
Glassmorphism Hover Transition — preview
Frost-reveal cards, layered depth buttons, profile cards with banner and avatar scale, and notification toasts with glass blur depth on hover.
18 / 22
Staggered List Animation
CSS + JS
Staggered List Animation — preview
Sequential entrance for tasks (slide left), feature cards (scale up), navigation menu (slide right) and data table rows (fade up) with replay controls.
19 / 22
Cursor Trail Effect
CSS + JS
Cursor Trail Effect — preview
Custom cursor dot and ring with four switchable trail modes: coloured dots, sparkle particles, comet streaks and rainbow — plus live position stats.
20 / 22
Magnetic Button Effect
CSS + JS
Magnetic Button Effect — preview
Buttons, icon links, nav items and FABs that translate toward the cursor within a 120px radius using mousemove vector math and spring easing.
21 / 22
Split Text Reveal Transition
CSS + JS
Split Text Reveal Transition — preview
Character-split hero headline, word-by-word reveal, rotating word swap, per-character colour wave and text scramble with progressive decode.
22 / 22
Progress Bar Animation
CSS + JS
Progress Bar Animation — preview
Labelled skill bars, shimmer and striped variants, thin page-load indicators, circular SVG rings and step segment indicators with animated fills.
FAQ

Frequently asked questions

What is the difference between a CSS transition and a CSS animation?
Both produce motion, but they're different tools. <strong><code>transition</code></strong> animates a property between two states — usually triggered by a state change like <code>:hover</code>, <code>:focus</code>, <code>:checked</code>, or a JavaScript class toggle. You declare the start state, declare the end state, and CSS interpolates between them. <strong><code>animation</code></strong> + <code>@keyframes</code> runs a multi-step sequence over time (can have 2, 5, or 50 intermediate states), runs on page load or via class toggle, can loop infinitely, and can chain via <code>animation-delay</code>. Decision tree: (1) State change like hover or click → use <code>transition</code> — simpler, fewer keystrokes, less code to maintain. (2) Looping motion (spinner, pulse, marquee, breathing button) → use <code>animation</code> — <code>transition</code> can't loop. (3) Multi-stage choreography (icon morphs through 4 shapes) → use <code>animation</code> — only @keyframes can express more than two states. (4) Scroll-driven motion → use <code>animation-timeline: scroll()</code> (Chrome 115+, Safari 18+) or a JS IntersectionObserver-triggered <code>transition</code>. All 22 demos in this collection use the right tool for each pattern.
How do I add button hover transitions without :hover breaking on touch devices?
Demo 01 (Button Hover Transitions) ships 9 production-grade variants that work correctly across mouse, touch, and pen inputs. The trick: <strong>never rely on <code>:hover</code> alone for state changes</strong> — it fires inconsistently on touch (some browsers fire <code>:hover</code> on tap and leave it stuck until another tap elsewhere; others skip it entirely). Three production-grade fixes that this demo applies: (1) <strong>Pair <code>:hover</code> with <code>:focus-visible</code></strong> so keyboard users get the same visual feedback. (2) <strong>Add <code>@media (hover: hover)</code></strong> wrapper around hover-only effects (cursor-attraction, magnetic pull, image zoom) so they don't fire weirdly on touch — only when a real mouse cursor is detected. (3) <strong>Use <code>:active</code> for tap feedback</strong> on mobile — the brief touchdown state gives users confirmation their tap was registered. The 9 button variants in Demo 01 (fill sweep, slide-up, neon glow, rotate icon, border draw, 3D depth, ripple ring, shimmer, split wipe) are each a self-contained CSS class you can copy into any button — semantic HTML, no library, ~10-25 lines of CSS per variant.
How do I do scroll-reveal animations without AOS.js, Framer Motion, or GSAP?
Demos 02 (Slide-In on Scroll) and 18 (Staggered List Animation) ship the vanilla pattern using IntersectionObserver — no library required. Cost comparison: <strong>AOS.js</strong> ships ~22kb minified for this effect. <strong>Framer Motion's <code>whileInView</code></strong> requires React + ~140kb motion library. <strong>GSAP ScrollTrigger</strong> is ~70kb. <strong>This demo's approach</strong>: ~15 lines of vanilla JavaScript using IntersectionObserver. The pattern: each <code>.reveal</code> element starts with <code>opacity: 0; transform: translateY(40px)</code>. A single IntersectionObserver watches all <code>.reveal</code> elements; when one enters the viewport, JavaScript adds an <code>.is-visible</code> class. The CSS <code>.is-visible</code> rule transitions opacity to 1 and transform to 0 over 0.7s. Total: ~600 bytes, zero dependencies, works in every framework or no framework. Plus the <code>prefers-reduced-motion</code> query disables the transform entirely for visitors with the OS preference set. Demo 18 adds staggered <code>transition-delay</code> values (100ms × index) so list items cascade in sequence instead of appearing simultaneously.
How do I build a production-grade 3D flip card transition?
Demo 03 (Flip Card 3D Transition) ships the canonical implementation that most online tutorials get wrong. The pattern requires three CSS properties working together: (1) <strong><code>perspective: 1000px</code></strong> on the parent scene container — this creates the 3D viewing distance. Without it, the rotation looks flat / glitchy. (2) <strong><code>transform-style: preserve-3d</code></strong> on the inner card flipper — without this, child elements collapse to 2D when the parent rotates. (3) <strong><code>backface-visibility: hidden</code></strong> on both faces — without this, you see the back of the front face mirrored through the card when it's mid-rotation. The flip itself is a single <code>transition: transform 0.6s cubic-bezier(.22,1,.36,1)</code> + <code>transform: rotateY(180deg)</code> on hover. Most tutorials skip <code>backface-visibility</code> or only apply it to one face — the result is text appearing backward during the flip. Bonus production detail: add <code>will-change: transform</code> on the flipper so the browser promotes it to a GPU layer before the animation starts, preventing first-frame stutter. Pure CSS, zero JavaScript.
How do I do page transitions in vanilla CSS / JS (Next.js / Vue Router / Astro alternative)?
Demo 12 (Page Transition Effect) ships the cross-framework pattern using the new <strong>View Transitions API</strong> (Chrome 111+, Safari 18+, Firefox 129+). The native API: wrap navigation in <code>document.startViewTransition(() => updateDOM())</code> — the browser automatically captures before/after snapshots and crossfades them. To customise: add CSS rules targeting <code>::view-transition-old(root)</code> and <code>::view-transition-new(root)</code> with custom animations (slide, fade, scale, blur). Demo 12 ships 4 transition variants: fade, slide-left, scale-up, blur-cross — switch between them with a button. Why use this over Framer Motion's <code>AnimatePresence</code> or Next.js page transitions: <strong>(a) zero bundle cost</strong> — it's a browser API. <strong>(b) cross-framework</strong> — works in Astro, Next.js, vanilla HTML, Vue Router, SvelteKit — anywhere you can call <code>startViewTransition()</code>. <strong>(c) GPU-accelerated</strong> — transitions run on the compositor thread, no React reconciliation pause. Fallback for older browsers: feature-detect <code>document.startViewTransition</code> and fall back to a synchronous update (no animation, page still works). ~30 lines of JS.
How do I build modal / dialog open-close transitions without animation libraries?
Demo 11 (Modal Open Close Transition) ships the production pattern using the native <code>&lt;dialog&gt;</code> element + CSS transitions. The platform-modern approach: semantic <code>&lt;dialog id="myModal"&gt;</code>, opened with <code>modal.showModal()</code> (which provides focus-trap, Esc-to-close, and scroll-lock for free — no library needed), closed with <code>modal.close()</code>. Animate the open with <code>@starting-style</code> (Chrome 117+, Safari 17.5+, Firefox 129+) for the entry transition: <code>@starting-style { dialog[open] { opacity: 0; transform: scale(0.9); } } dialog[open] { opacity: 1; transform: scale(1); transition: all 0.3s; }</code>. For the close: <code>transition-behavior: allow-discrete</code> + <code>display: block</code> in the closed state. Cost comparison: <strong>Framer Motion's <code>&lt;AnimatePresence&gt;</code></strong> + a custom dialog implementation = ~140kb React + Motion + focus-trap libraries. <strong>This demo's approach</strong>: ~25 lines of vanilla JavaScript (open/close handlers + backdrop click) + ~40 lines of CSS. Zero library bundle, full keyboard accessibility from the native dialog element, works in every framework. Browser support: native <code>&lt;dialog&gt;</code> is Chrome 37+, Safari 15.4+, Firefox 98+ — universally supported as of 2024.
How do I create skeleton loader transitions (Facebook / LinkedIn style)?
Demo 10 (Loading Skeleton Transition) ships the shimmer-bar pattern that Facebook, LinkedIn, and YouTube use during content load. The pattern: skeleton boxes are gray placeholders matching the eventual content's shape (avatar circle, two text bars, image rectangle), with a moving shimmer gradient overlay. Pure CSS implementation: each skeleton element has <code>background: linear-gradient(90deg, #e0e0e0 0%, #f5f5f5 50%, #e0e0e0 100%); background-size: 200% 100%</code> and runs <code>animation: shimmer 1.5s infinite</code> that animates <code>background-position</code> from <code>200% 0</code> to <code>-200% 0</code>. The shimmer band sweeps across the placeholder, signaling "loading" without a spinner. JS toggles the skeleton state — replace skeleton DOM with real content when fetch completes. Cost comparison: <strong>React Skeleton library</strong> ships ~8kb + requires React. <strong>This demo's approach</strong>: ~20 lines of CSS, framework-neutral, works in any stack. Three production-grade details most tutorials miss: (1) <strong>Match the skeleton's exact dimensions to the real content</strong> — otherwise users see layout shift (LCP penalty) when content replaces skeleton. (2) <strong>Add <code>prefers-reduced-motion</code> fallback</strong> — replace the shimmer animation with a static gray for visitors with motion sensitivity. (3) <strong>Show skeleton only after 200ms</strong> — if content loads faster, skip skeleton entirely (no flash-of-loading-state).
How do I build a cursor trail effect (Awwwards-winning sites style)?
Demo 19 (Cursor Trail Effect) ships the production-grade implementation made famous by Awwwards-winning portfolio sites and the Stripe Sigma landing page. The mechanic: on <code>pointermove</code> across the viewport, JavaScript captures the cursor coordinates and spawns trail dots at decreasing opacity values that follow the cursor with a slight lag. Three implementation strategies, ranked by performance: (1) <strong>Best — recycle a fixed pool of 20-30 trail dots</strong>, updating their transform position with each move event. No DOM creation/destruction in the hot path → 60fps even on mid-tier mobile. (2) <strong>OK — spawn new dot per move event, remove via animationend</strong> — works but creates DOM churn that can stutter at high mouse speeds. (3) <strong>Avoid — Canvas trail with requestAnimationFrame redraw</strong> — looks great but eats 8-15ms scripting per frame, tanking INP score on lower-end devices. This demo uses approach (1) — ~80 lines of vanilla JS, no library. Three production gotchas: (a) <strong>Skip on touch devices</strong> via <code>matchMedia('(hover: none)')</code> — pointer-move on touch is gesture-not-cursor. (b) <strong>Respect <code>prefers-reduced-motion</code></strong> — disable the trail entirely for vestibular-sensitive visitors. (c) <strong>Cap the trail at 30 dots maximum</strong> — beyond that, the visual gets noisy and the perf cost compounds.
Will animating box-shadow, filter, or background-color hurt my Core Web Vitals INP score?
Short answer: <strong>animating <code>box-shadow</code> and <code>filter</code> can hurt INP significantly; animating <code>background-color</code> is usually fine.</strong> Here's the breakdown. <strong>Animatable on the compositor (cheap, 60fps)</strong>: <code>transform</code> (translate/rotate/scale), <code>opacity</code>. These don't trigger layout or painting — they run on the GPU thread. All 22 demos in this collection use these primarily. <strong>Animatable but expensive (paint cost per frame)</strong>: <code>background-color</code>, <code>color</code>, <code>border-color</code> — these require repainting the element each frame, costing 2-4ms per frame. Usually fine for a single element; tanks INP if you animate 50+ elements simultaneously. <strong>Avoid animating</strong>: <code>box-shadow</code>, <code>filter: blur()</code>, <code>border-radius</code>, <code>width</code>, <code>height</code>, <code>top</code>, <code>left</code>, <code>margin</code>, <code>padding</code>. These trigger expensive recalculations — animating <code>filter: blur(0px) → blur(20px)</code> on hover can cost 16-30ms per frame, single-handedly failing INP. <strong>Workaround for shadow / blur effects</strong>: pre-render the blurred/shadowed state as a separate element with <code>opacity: 0</code>, then transition opacity 0 → 1 on hover. The browser composites the two states instead of recalculating the filter — drops paint cost from 30ms to under 1ms. Demo 17 (Glassmorphism Hover) uses this opacity-cross-fade trick for the backdrop-filter blur.
Which CSS transition effect should I use for my project?
Quick decision guide. <strong>Button feedback</strong>: Demo 01 (Button Hover Transitions — 9 variants). <strong>Hero section / landing page elements appearing on scroll</strong>: Demo 02 (Slide-In on Scroll). <strong>Product cards or testimonials revealing on scroll</strong>: Demo 18 (Staggered List Animation). <strong>Service / pricing cards with flip interaction</strong>: Demo 03 (Flip Card 3D Transition). <strong>Editorial text intro</strong>: Demo 04 (Text Reveal Animation) for masked clip reveal; Demo 21 (Split Text Reveal) for GSAP-style word-by-word. <strong>E-commerce / portfolio image gallery</strong>: Demo 05 (Image Zoom Hover) for product cards; Demo 16 (Card Tilt 3D Hover) for premium feel. <strong>Form button or theme toggle</strong>: Demo 06 (Background Color Transition). <strong>CTA emphasis</strong>: Demo 07 (Border Animation). <strong>Tabs or accordion content</strong>: Demo 08 (Fade In/Out). <strong>Navigation menu</strong>: Demo 09 (Navigation Hover). <strong>Skeleton loading state</strong>: Demo 10 — replaces spinners. <strong>Modal / dialog</strong>: Demo 11 — uses native <code>&lt;dialog&gt;</code>. <strong>SPA-like page transitions</strong>: Demo 12 — uses View Transitions API. <strong>Material click feedback</strong>: Demo 13 (Ripple on Click). <strong>Link hover states</strong>: Demo 14 (Underline Animation). <strong>Stats / metric blocks</strong>: Demo 15 (Number Counter). <strong>Glassmorphism brand</strong>: Demo 17 — frosted glass hover. <strong>Awwwards-style portfolio</strong>: Demo 19 (Cursor Trail) + Demo 20 (Magnetic Button). <strong>Progress / completion indicator</strong>: Demo 22 (Progress Bar). All 22 demos respect prefers-reduced-motion, are MIT-licensed, GPU-accelerated, and work in every framework or no framework.

Related collections

15 CSS Background Animations preview

15 CSS Background Animations

15

15 hand-coded CSS background animations with live demos — infinite shifting gradient, floating particle bubbles, parallax starry night, clickable cyberpunk ripple, sliding geometric grid, SVG wave overlays, glassmorphism orbs, aurora borealis ribbons, matrix digital rain, mesh gradient blobs, falling snow, morphing blob, retro synthwave 3D grid, infinite scrolling diagonal marquee, comic-book halftone dots. 100% Pure CSS, no JavaScript, no canvas, no particles.js. prefers-reduced-motion respected, scoped class names, MIT-licensed.

css background animation animated gradient background css css floating particles Responsive
27 CSS Button Hover Effects preview

27 CSS Button Hover Effects

27

27 hand-coded CSS button hover effects — 3D press, neon glow, gradient slide, border draw, liquid fill, ripple, glitch text, and kinetic flips. Every demo is pure CSS (no JavaScript, no framework), tuned for 60fps with transform and opacity, and respects prefers-reduced-motion out of the box.

css buttons button hover button hover effects Responsive
33 CSS Card Hover Effects preview

33 CSS Card Hover Effects

33

33 hand-coded CSS card hover effects with live demos — multi-axis 3D tilt with parallax, glowing gradient glassmorphic border, image zoom with content slide-up, front-to-back 3D flip, sibling de-emphasis with :has(), minimalist elevation, plus 27 more (elastic lift, conic-gradient border, holographic foil, neon sign, glitch RGB split, magnetic float, blueprint reveal, aurora drift and more). 26 pure CSS + 7 with a small vanilla JS snippet for cursor tracking. prefers-reduced-motion respected, scoped class names, MIT-licensed.

css card hover effect css card hover animation card hover effect pure css Responsive

Search CodeFronts

Loading…