16 copy-paste CSS pulse animation templates built as real-world use cases — landing-page CTA button pulse, mobile FAB ripple, video play overlay halo, e-commerce Add-to-Cart hover-triggered double pulse, notification bell badge, live status dot, ECG heartbeat waveform, DevOps server status ring, recording indicator, map pin drop, skeleton loader shimmer, form submitting state, load-more staggered dots, wishlist heart cardiac rhythm, voice search mic listening pulse, and security scan overlay. Every pulse animates only transform, opacity, and box-shadow — the three GPU-compositor-safe properties that keep 60fps on real mobile hardware. Animating raw width, height, margin, or padding would tank INP scores; every demo here avoids that trap. Scoped under .pl-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.

14 pure CSS2 light JSPublished

Related12 CSS Ripple Effects16 CSS Bounce Animations30 CSS Keyframe Animations

Pulse Button CTA — preview
01 / 16Pure CSS

Pulse Button CTA

A primary call-to-action button with an infinite cyan pulse ring emitting from the button edge — the standard evergreen pattern for "Sign up" / "Get started" / "Talk to sales" landing-page CTAs. Deep navy fintech palette (Stripe / Vercel / Linear landing-page convention) with electric cyan #00d4ff accent. The ring is a ::after pseudo-element animated via box-shadow outward-cast — button text stays perfectly readable through the pulse.

Published

FAB Ripple Pulse — preview
02 / 16Pure CSS

FAB Ripple Pulse

A floating action button (FAB) with an outward ripple pulse for mobile app dashboards — the sticky bottom-right "+" or "chat support" button that draws attention to the primary action hub. Warm off-white iOS consumer app palette with coral #ff6b6b FAB, mock dashboard content behind (feed cards, avatar bar), FAB positioned absolute; bottom: 24px; right: 24px. The ripple uses dual ::before and ::after pseudo-elements with staggered animation-delay for a continuous concentric outward wave.

Published

Video Play Button Overlay Pulse — preview
03 / 16Pure CSS

Video Play Button Overlay Pulse

A landing-page hero video overlay — dark cinematic thumbnail with a static amber play triangle in a circular container that casts an expansive transparent pulsing shadow outward. The pulse tempts a click without competing with the video itself. Editorial dark palette (#0d0d10) with amber #f59e0b play button — New Yorker / The Atlantic / editorial video convention. Playfair Display headline overlay for magazine-cinematic feel.

Published

Add to Cart Hover Pulse — preview
04 / 16Pure CSS

Add to Cart Hover Pulse

An artisan e-commerce product card with an Add-to-Cart button that pulses continuously while the pointer is hovering — a hover-gated micro-interaction confirming interactive readiness without the always-on infinite pulse of standalone CTAs. Cream #fdf6e3 + forest green #166534 palette (Everlane / Allbirds / artisan e-commerce convention) with Playfair Display serif product name. Hover-triggered means resting state is calm; pulse activates only when the user signals intent by hovering, and continues for as long as the pointer stays.

Published

Notification Bell Badge Pulse — preview
05 / 16Pure CSS

Notification Bell Badge Pulse

A business SaaS app header with a bell icon and an unread-count badge that pulses to draw the eye — Notion/Linear/Superhuman header convention. Clean white surface (#ffffff) with slate ink (#0f172a) and a red badge (#ef4444). Only the badge itself pulses (subtle scale + box-shadow ring), the bell stays still. The pattern signals "new alert" without being distracting because the pulse animates the smallest UI element on the page — an 18px circle — not the entire header.

Published

Live Status Dot — preview
06 / 16Pure CSS

Live Status Dot

A streaming platform / chat app live-status indicator — small neon-lime dot with a soft continuous radiating ring signaling that a stream, user, or server is actively "live" right now. Charcoal (#1a1a1a) streamer-lounge palette with neon lime (#84cc16) status color — Twitch / Discord / OBS-adjacent aesthetic. The dot appears in three real contexts within one demo: header ("12,400 watching"), stream card ("LIVE"), and channel list (with viewer count) — showing the pattern's versatility.

Published

ECG Heartbeat Line — preview
07 / 16Pure CSS

ECG Heartbeat Line

A medical vitals monitor with an animated ECG heartbeat waveform sweeping left-to-right across a grid, matched to numeric vitals (HR, SpO2, BP, Resp) in a telehealth dashboard layout. Medical blue (#2563eb) + mint (#10b981) trace with clinical white surface (#ffffff) and grid graph background — Epic MyChart / Teladoc / Withings clinician-facing convention. Uses a pure-SVG animated stroke-dashoffset for the trace + a running dot marker.

Published

Server Status Ring — preview
08 / 16Pure CSS

Server Status Ring

A DevOps operations-center dashboard with server-status rings — 4 tiles each showing a service, its uptime, and a concentric pulsing ring indicating health status. Terminal-green healthy state (#22c55e) with amber warning (#f59e0b) tile mixed in for realism. Datadog / PagerDuty / Grafana ops-center aesthetic with all-uppercase JetBrains Mono labels, deep-forest surface (#0a3a1f), and hostname / region metadata.

Published

Recording Indicator — preview
09 / 16Pure CSS

Recording Indicator

A screen-recorder UI mockup with an active recording dot — pulsing red camera indicator + running timer + recording controls (pause / stop / mic / camera). Loom / Riverside / Zoom recording aesthetic with cool-gray (#f1f5f9) surface, deep slate ink (#0f172a), and red (#dc2626) recording state. The dot uses a subtle opacity pulse (not scale) because recording indicators must NEVER feel frivolous — this is a data-capture context where users need to trust the app is genuinely recording.

Published

Map Pin Drop Pulse — preview
10 / 16Pure CSS

Map Pin Drop Pulse

A delivery / rideshare map view with a custom map pin marking a driver's current location. The pin sits on the map with a wide concentric ring pulsing on the ground layer below it — signaling "active geo-tracking, here right now." Sage map palette (#a3b18a) with cross-hatched road overlays, deep navy pin (#1e3a8a) with white shadow, and a soft ETA card overlay in the bottom corner ("7 mins away" pattern from DoorDash / Uber driver-arrived flow).

Published

Skeleton Loader Card Pulse — preview
11 / 16Pure CSS

Skeleton Loader Card Pulse

Content-loading skeleton screens — the LinkedIn / Facebook / YouTube pattern for graceful data fetching. 3 stacked feed cards each with an avatar circle, author line, three text blocks, and a media thumbnail — all animated with a diagonal shimmer sweep that reads as "content is on its way." Neutral gray canvas (#f8fafc) with light gray placeholders (#e2e8f0) and a bright shimmer highlight (#f8fafc) sweeping diagonally.

Published

Form Submitting Pulse — preview
12 / 16CSS + JS

Form Submitting Pulse

A B2B signup form with a submit button that transforms into a processing-pulse state on click — text disappears, replaced by a soft scale-pulse loader indicating the API request is in flight. Muted purple (#6b46c1) accent on soft lavender background (#f5f3ff) — Superhuman / Vercel / Linear signup aesthetic. The pulse is DELIBERATELY calm (not spinning, not bouncing) because form submission is a trust context — the user just gave you their data and needs to feel it's being handled competently.

Published

Load More Staggered Dots — preview
13 / 16Pure CSS

Load More Staggered Dots

An infinite-scroll feed pagination indicator — three horizontal slate dots pulsing in a staggered sequence at the bottom of a feed container, signaling "loading more content, hang on." Neutral off-white canvas (#fafafa) with slate (#475569) dots and light gray ghost cards above (representing already-loaded content). Twitter / Threads / Reddit infinite-scroll aesthetic — quiet, minimal, honest.

Published

Pulsing Heart Icon — preview
14 / 16Pure CSS

Pulsing Heart Icon

A wishlist / save-for-later heart button on a product card — the heart pulses with a natural cardiac rhythm (not a mechanical scale), giving the interaction warmth and personality. Warm pink card (#fecaca to #fff1f2) with crimson heart (#dc2626) and a small saved-count badge. Pinterest / Airbnb / Instagram save button aesthetic. The keyframe uses cardiac timing (0% → 20% quick scale-up → 40% pull-back → 60% settle) that mimics a real heartbeat's systole-diastole rhythm — the reason this pattern feels alive, not robotic.

Published

Voice Search Mic Pulse — preview
15 / 16CSS + JS

Voice Search Mic Pulse

A voice-assistant modal showing an active listening state — microphone icon at the center with expanding concentric rings pulsing outward + a live waveform of vertical bars responding to "voice input." Deep purple gradient background (#4c1d95 to #7c3aed) with white mic icon and glassmorphic modal card. Google Assistant / Alexa / Siri modal aesthetic. The pulse conveys "I'm actively listening, keep speaking."

Published

Icon Scan Overlay — preview
16 / 16Pure CSS

Icon Scan Overlay

A security-scanner HUD showing an active malware / virus scan in progress — a shield icon at the center with rapid concentric green rings firing outward, matched to a scan progress bar and file-processing terminal output. Terminal-black surface (#000000) with toxic-green scan color (#22c55e) and JetBrains Mono uppercase labels. Malwarebytes / Kaspersky / Norton / Trellix scan-in-progress aesthetic — dev-culture technical, not consumer-friendly.

Published

FAQ

Frequently asked questions

What is a CSS pulse animation and what's the canonical recipe?
A CSS pulse animation is a repeating outward-radiating visual effect — a ring, halo, or scale-fade — used to draw attention to interactive elements without displacing them. The canonical recipe uses only three GPU-compositor-safe properties: transform, opacity, and box-shadow. For a rectangular button, use box-shadow outward-cast: animation: pulse 1.8s infinite; @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(brand, .5); } 70%, 100% { box-shadow: 0 0 0 18px rgba(brand, 0); } }. The 0 0 0 Npx spread grows outward while alpha fades to 0. box-shadow is chosen over outline or scaled pseudo-elements because it preserves the button's border-radius perfectly at every frame — a scaled pseudo-element distorts corners on non-square buttons. For a CIRCULAR element (FAB, dot, play button), use transform: scale on a pseudo-element instead: ::after { content: ''; position: absolute; inset: 0; border-radius: 50%; background: currentColor; animation: ripple 1.8s infinite; } @keyframes ripple { 0% { transform: scale(1); opacity: .5; } 100% { transform: scale(2.2); opacity: 0; } }. The scale is clean on circles because the shape doesn't distort. Both patterns keep the animation compositor-only (no layout, no paint) — the browser can push these frames to the GPU without triggering reflow. This is the difference between smooth 60fps on mid-tier mobile and jerky 15fps on old Android. Every demo in this collection uses one of these two patterns.
Why does animating width/height/margin/padding kill performance, and what breaks?
Animating width, height, margin, or padding forces the browser to run a full layout + paint + composite pipeline on every animation frame — 60 times per second. The layout stage is expensive because ANY size change on ANY element potentially forces the browser to reflow its siblings, its parent, and every descendant. Paint then rebuilds the pixel buffer for every affected region. Composite finally uploads the new pixels to the GPU. On mid-tier mobile (mid-2020s Android, entry iPhones), this pipeline can take 10-16ms per frame — right at the edge of the 16.67ms budget for 60fps. Add one animated pulse ring using width: 20px → 60px and you're at 22ms per frame → 45fps. Add three concurrent pulses → 33ms → 30fps → visible stutter. Now measure your INP (Interaction to Next Paint) — it will hit 200ms+ on real hardware, and Google flags this as "Poor" in Core Web Vitals. Your Search Console will show the regression within days. The compositor-only alternative: transform and opacity skip layout and paint entirely — they run on the GPU compositor thread. box-shadow is technically a paint operation but modern browsers (Chrome 90+, Safari 15+, Firefox 89+) push it to the compositor for animation. So a 30-instance pulse using transform: scale or box-shadow spread runs at consistent 60fps even on 3-year-old Android hardware — because the CPU-side layout thread is never touched. This is not premature optimization; it's the difference between shipping and being penalized in Search Console.
How do I make the pulse fire only on hover / click / focus instead of infinitely?
For hover-triggered pulses (Add-to-Cart micro-interactions, Product hotspots, tooltip anchors), use animation-play-state: define the animation on the pseudo-element in the RESTING state with animation-play-state: paused, then flip it to running inside the :hover pseudo-class. Example: .btn::after { animation: pulse .8s ease-out 2; animation-play-state: paused; } .btn:hover::after { animation-play-state: running; }. Critically, the animation is DECLARED in the base rule so :hover only flips the play state. If you write animation INSIDE :hover, the animation restarts from 0% on every hover-in and reset feels janky. The animation-iteration-count: 2 gives you a bounded double-pulse (a burst that confirms readiness and then goes quiet); infinite hover pulse is disorienting and reads as "the button is broken." For touch devices where :hover isn't reliable, wrap the trigger in @media (hover: hover) so touch users get the button without the pulse trigger. For click-triggered one-shot pulses (submit confirmation, item added animation), use :active instead of :hover, and switch to animation-iteration-count: 1 so it fires exactly once per click. For focus-triggered pulses (keyboard accessibility), use :focus-visible instead of :focus — the -visible variant fires only for keyboard focus, not mouse-click focus, so mouse users don't see a distracting pulse on every button click. Demo 04 (Add to Cart Hover Pulse) ships the canonical hover-triggered double-pulse pattern with the @media (hover: hover) guard for touch devices.
How do I respect prefers-reduced-motion — and when should the pulse disappear vs stay static?
The rule differs by intent tier. For decorative pulses (CTA buttons, FAB ripples, video play halos, ambient background glows), prefers-reduced-motion: reduce should DISABLE the pulse entirely — @media (prefers-reduced-motion: reduce) { .pulse-el::after { animation: none !important; } }. The element stays functional and clickable; the decorative pulse just doesn't animate. For informational pulses that carry meaning (Live status dot, Recording indicator, ECG heartbeat), the pulse cannot fully disappear because it conveys "this is active" or "recording is in progress" — critical information. The fallback here is to keep a STATIC saturated color state that clearly reads as "active" without animation. Example: a Live status dot animates a green pulse ring in normal motion, but in reduced-motion it shows a solid green dot with no ring — the user still sees "this is live," they just don't see it pulsing. This tiered approach follows WCAG 2.3.3 (Animation from Interactions) and respects WCAG 2.2.2 (Pause, Stop, Hide). WCAG 2.2.2 specifically says: any animation over 5 seconds must have a pause control; under 5 seconds is fine without controls. All 16 demos in this collection cycle under 3 seconds, so no pause controls needed — but reduced-motion must still be respected for users with vestibular disorders. Every demo in this collection ships the reduced-motion guard already.
What's the difference between using box-shadow and transform: scale for a pulse ring?
Both are compositor-safe, but they solve different shape problems. box-shadow is best for non-circular elements — buttons with rounded rectangles, chips, cards. The shadow spread grows outward from the element's border-radius, perfectly matching its shape at every frame. A rounded-rectangle button gets a rounded-rectangle pulse; a squircle badge gets a squircle pulse. Transform: scale on a pseudo-element is best for circular or square elements — FABs, dots, play buttons, badges. Scaling a circular ::after preserves the circle perfectly. But scaling a rounded-rectangle pseudo-element distorts the corners nonlinearly (the border-radius scales along with everything else, so what was a subtle 10px radius becomes an oversized 22px radius at scale(2.2) — the corners visibly bulge outward). Trade-off summary: box-shadow = shape-safe on ANY element, single ring per animation (needs multiple pseudo-elements for multi-ring). Transform: scale = shape-safe only on circles/squares, works cleanly with dual pseudo-elements for continuous concentric waves. Demos 01, 04 use box-shadow (rectangular buttons); Demos 02, 03 use transform: scale (circular FAB, play button). For a rectangular button with a multi-ring cascade, combine both: box-shadow on the button itself for the outermost ring, transform: scale on staggered pseudo-elements INSIDE the button for inner rings. Rare pattern, useful for dramatic hero CTAs.
How do I stack multiple pulse animations on one page without performance regressions?
Every pulse animation gets its own GPU compositor layer, so 30 concurrent pulses use ~30 layers. Modern browsers cap active compositor layers around 50-100 before performance degrades. Practical rules: (1) Use will-change: transform on the animated element — tells the browser to promote to a compositor layer immediately, avoiding a promotion delay on animation start. But use SPARINGLY: will-change on every pulse permanently reserves GPU memory. Apply only to elements that are ACTIVELY animating and remove after. (2) Avoid pulsing more than 10-15 elements simultaneously on one page. If your page has 50 product cards each with an Add-to-Cart pulse, only the currently-hovered card's pulse should be running — use the hover-triggered pattern (Demo 04) so 49 pulses are paused at any given moment. (3) For always-on pulses (Live status dots, Recording indicators), reserve them for elements above-the-fold or currently visible. Use IntersectionObserver to pause pulses on elements scrolled out of view: const io = new IntersectionObserver(entries => entries.forEach(e => e.target.style.animationPlayState = e.isIntersecting ? 'running' : 'paused')); io.observe(dot);. This trims a 50-dot ops dashboard down to 8-12 actively animating dots at any moment. (4) On mobile, respect the battery-saver signal: navigator.connection.saveData or matchMedia('(prefers-reduced-data: reduce)') — if either is true, disable all decorative pulses (same as reduced-motion). This is not documented behavior yet, but Chrome ships the signal and battery-conscious users appreciate it.
What are the top real-world use cases for pulse animations in production apps?
The 16 patterns in this collection cover the production canon, organized by user intent tier. Attention / CTA (5 patterns): (1) Pulse Button CTA — landing-page "Book a call" / "Get started" buttons where the pulse indicates the primary conversion action. (2) FAB Pulse — mobile app bottom-right create/chat FAB, the always-visible primary action hub. (3) Video Play Overlay — landing-page hero video with an amber play button pulse tempting the click. (4) Add-to-Cart Hover Pulse — e-commerce product cards where the hover-triggered double-pulse confirms interactive readiness. (5) Notification Bell Badge — app header bell with a snappy pulse when the unread count changes. Live / Status indicators (5 patterns): (6) Live Status Dot — chat / streaming / server "online" indicator, tiny green dot with radiating soft ring. (7) ECG Heartbeat Line — medical monitor waveform for telehealth and fitness dashboards. (8) Server Status Ring — DevOps ops center (Datadog / PagerDuty pattern) with 3-ring concentric SLA health indicator. (9) Recording Indicator — red camera dot for video/audio capture UIs (Loom / Zoom / Riverside). (10) Map Pin Drop Pulse — delivery / rideshare apps with a geo-tracking marker. Async / Feedback (3 patterns): (11) Skeleton Loader Card Pulse — content-loading placeholder shimmer (LinkedIn / Facebook feed pattern). (12) Form Submitting Pulse — button state pulse while API request is in flight. (13) Load More Staggered Dots — infinite-scroll feed pagination indicator. Specialty / Aesthetic (3 patterns): (14) Pulsing Heart Icon — wishlist / social liking with cardiac-rhythm keyframes (0% → 20% scale-up → 40% pull-back → 100% return). (15) Voice Search Mic Pulse — voice UI listening state (Google Assistant / Alexa modal). (16) Icon Scan Overlay — security scanning HUD (Malwarebytes / Kaspersky pattern) with rapid concentric outward rings. Every pattern is copy-paste ready with industry-appropriate palette and typography — drop into your fintech / e-commerce / medical / DevOps / consumer app without stripping generic styling.

Related collections

20 CSS Animated Buttons preview

20 CSS Animated Buttons

20 hand-coded CSS animated buttons — neon glow, ripple, 3D press, liquid fill, jelly bounce, shine sweep, animated border, moving gradient CTA, text flip, submit success state, add-to-cart progress, download icon, hamburger-to-close, toggle switch, loading spinner inside button, next/prev arrow nav, and ghost button background reveal. Half pure CSS, half lightweight JS for production interactions.

11 CSS animation-timeline Demos preview

11 CSS animation-timeline Demos

11 pure CSS animation-timeline demos built on the W3C scroll() and view() spec — reading progress bar, view-timeline fade & reveal, shrinking sticky header, stacking cards, horizontal scroll section, parallax hero, container shadow indicators, reverse-scroll columns, text scrim reveal, cover card to sticky header, and image zoom / clip-path wipe. Zero JS, off the main thread, Core Web Vitals safe. Copy-paste ready.

25 CSS Background Animations preview

25 CSS Background Animations

25 hand-coded CSS background animations for SaaS hero sections, developer tool documentation, agency portfolios, gaming and Web3 landing pages, seasonal e-commerce campaigns, and dark-mode dashboards. Covers full-screen gradient shifts, animated mesh gradients, aurora borealis glow, cursor spotlight follow, interactive water ripples, dot grid and diagonal stripe patterns, SVG grain and noise texture overlays, topographic contour lines, layered SVG waves, plasma and lava lamp fluids, bokeh light blur, particle constellation networks, matrix digital rain, synthwave 3D perspective grids, starfield warp speed, CRT scanline overlays, fog and mist drift, morphing organic blobs, floating glassmorphism orbs, halftone dot patterns, starry night skies, floating geometric shapes, rising bubbles, and falling snow. 20 are pure CSS with zero JavaScript; the 5 that need it use vanilla canvas or pointer tracking with no dependencies. Every background animates compositor-only properties so it never blocks the main thread, is scoped under a .bga-NN prefix for no-collision pasting, guards prefers-reduced-motion, and ports unchanged to React, Vue, Svelte, Astro, Next.js and Tailwind.

Search CodeFronts

Loading…