webdevpuneet.com

Heartbeat Pulse Monitor Loader — Free HTML CSS JS Snippet

Heartbeat Pulse Monitor Loader · Loaders · Plain HTML, CSS & JS · Live preview

CategoryLoaders

Copy & paste

Source Code

<div class="hb-stage">
  <div class="hb-monitor" role="status" aria-label="Checking connection">
    <svg id="hbSvg" viewBox="0 0 400 120" preserveAspectRatio="none"></svg>
    <div class="hb-readout">
      <span class="hb-bpm" id="hbBpm">72</span>
      <span class="hb-bpm-unit">bpm</span>
    </div>
  </div>
  <p class="hb-hint" id="hbHint">Checking connection…</p>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Real QRS-complex-shaped waveform (flat, Q dip, R peak, S dip, T wave) built from explicit point data, not a generic sine wave
Seamless infinite horizontal scroll with no visible loop seam or reset jump
Bright sweeping scan head clipped via SVG clip-path, revealing the live trace only up to the current sweep position
Scroll speed mathematically derived from a real BPM value shared with the live readout, not two independently-tuned numbers
Scan head vertically tracks the actual waveform height as it sweeps, rather than moving in a straight line
Live bpm readout with subtle randomized jitter so it reads as monitoring, not a frozen static number
Cycling status text for a sense of ongoing multi-stage connection or verification work
Pure inline SVG, CSS, and requestAnimationFrame — no charting or animation library

About this UI Snippet

Heartbeat Pulse Monitor Loader — ECG Waveform with a Sweeping Scan Head

Screenshot of the Heartbeat Pulse Monitor Loader snippet rendered live

A heartbeat monitor loader mimics a hospital ECG display: a repeating spike-shaped waveform scrolls continuously across a dark screen, with a bright leading edge sweeping left to right and a bpm readout ticking nearby. Unlike a generic pulsing dot, this snippet draws an actual shaped waveform — a flat baseline, then a small dip, a sharp upward spike, a dip below baseline, and a rounded bump, matching the real QRS-complex shape of a heartbeat trace — repeated end-to-end so it reads unmistakably as "heartbeat" rather than an arbitrary wiggle.

Building one repeatable waveform unit

beatUnit(unitWidth) constructs a single beat as an ordered array of [x, y] points: a long flat segment (most of a real heartbeat cycle is a flat baseline between beats), followed by a small Q dip, a sharp R peak, an S dip below the baseline, and a rounded T wave, then a short flat tail padding the unit back out to its full width. This exact five-part shape — flat, small-dip, sharp-spike, dip, rounded-bump, flat — is what a real single-lead ECG trace looks like, and repeating this one unit via pathFromUnits(count, xOffset) is what produces a continuous, recognizably medical waveform instead of a looping sine wave.

Seamless infinite scroll with two trace layers

A dim, low-opacity trace (.hb-trace-dim) renders the full repeating waveform shape at rest across the whole visible width, giving the eye context for the shape even in the portion that hasn't "played" yet. A brighter, glowing live trace is layered on top but clipped with an SVG <clipPath> rect whose width grows with elapsed time — so the bright trace only ever shows up to the current sweep position, exactly like a real monitor where the newest sample is drawn and the sweep continues past what's already been shown. Both traces scroll using the same scrollX = (elapsed * pxPerMs) % UNIT_W calculation, so the waveform never visibly jumps or resets even though it loops indefinitely.

Deriving pixel speed from a real BPM value

Rather than an arbitrary animation duration, pxPerMs is derived directly from BPM: msPerBeat = 60000 / BPM, then pxPerMs = UNIT_W / msPerBeat. This means the waveform's visual scroll speed is mathematically tied to the displayed beats-per-minute number — changing BPM changes both the readout and the actual scroll speed together, keeping them honest with each other rather than being two independently-set values that happen to look plausible together.

A scan head that tracks the current waveform height

The small bright dot (scanHead) doesn't just travel in a straight horizontal line — its cy is set every frame by finding the nearest point in the unit array to the current sweep position within its cycle, so the dot visually rides along the top of the spike as it passes through, rising sharply during the R peak and dipping during the S trough, reinforcing that it's the leading edge actively drawing the trace rather than a decoration moving independently of it.

Subtle liveness details

The bpm readout jitters by a small random amount every 1.4 seconds and the status text below the monitor cycles through a short list of connection-themed phrases — small touches that keep a loading state that could run for many seconds from reading as visually frozen or fake.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSAn ECG-style waveform scrolls continuously with a bright sweeping scan head and a live bpm readout.
  2. 2
    Watch the scan head trace the waveformThe leading dot rises and dips exactly along the spike shape as it sweeps, not in a straight line.
  3. 3
    Change the simulated heart rateEdit the BPM constant — both the readout and the actual scroll speed are derived from it together.
  4. 4
    Adjust the waveform shapeEdit the point arrays inside beatUnit() to change the spike height, dip depth, or flat-segment proportion.
  5. 5
    Recolor the themeEdit the green color values in the CSS for a different monitor palette.
  6. 6
    Customize the status textEdit the messages array in the JS panel to match your own loading copy.

Real-world uses

Common Use Cases

Connection and session verification loaders
A literal, on-theme fit for "checking connection" or "verifying session" loading states in health, fitness, or monitoring apps.
Health and fitness dashboard loading states
Use while live vitals or wearable data is being fetched, reinforcing the product's health-monitoring theme even during a loading state.
System-status and uptime monitoring UI
Pair with a status icon morph spinner as a "vital signs" themed indicator for infrastructure health dashboards.
Onboarding or splash-screen loading moments
A distinctive, on-brand alternative to a generic spinner for products with a health or biometric angle.
AI / background processing indicators
A richer alternative to a plain progress bar, similar in spirit to the radar sweep scan loader but with a medical-monitor motif.
Studying seamless SVG scroll-loop techniques
A concrete reference for building an infinitely-looping scrolling trace with a clipped live layer over a dim background layer.

Got questions?

Frequently Asked Questions

beatUnit() builds one beat as an explicit ordered array of [x, y] points: a long flat baseline segment, a small downward Q dip, a sharp upward R peak, a deeper S dip below the baseline, a rounded T wave bump, then a short flat tail. This matches the real shape of a single-lead ECG trace, and pathFromUnits() repeats this one unit end-to-end to build the full scrolling waveform.

Both the dim background trace and the bright live trace are drawn from the exact same repeating unit and shifted by the same scrollX = (elapsed * pxPerMs) % UNIT_W value every frame. Because the waveform unit is periodic and the shift wraps at exactly one unit width, there is no discontinuity at the wrap point — the pattern simply continues.

msPerBeat is computed as 60000 / BPM (milliseconds per beat from beats-per-minute), and pxPerMs is then UNIT_W / msPerBeat — the width of one waveform unit divided by how long one beat should take. Changing the BPM constant changes both the readout and the actual pixel scroll speed together, since both derive from the same value.

Every frame, the scan head's vertical position is set by finding the point in the beatUnit array closest to the current position within its cycle, rather than staying fixed at the baseline height. This makes the leading dot visually ride along the top of the spike as it sweeps through it, reinforcing that it is the trace's actively-drawing edge.

An SVG clipPath contains a rect whose width is updated every frame to match the current sweep x-position (headX). The bright live trace path has that clip-path applied, so only the portion of the trace to the left of the current sweep position is visible in the bright color — everything to the right remains hidden until the sweep reaches it, exactly like a real ECG monitor's drawing behavior.

Precompute the beatUnit point array once (e.g. in useMemo) since it never changes, then run the requestAnimationFrame loop in a mount effect that updates the SVG path d attributes and the clip rect width via refs, with cleanup that cancels the animation frame and both intervals on unmount.