motion-progress

Fixed scroll-progress bar driven by Motion's scroll(). Spring-eased scaleX, so the bar settles past its target instead of hard-snapping.

Preview

The bar pinned to the top of every docs page is a live motion-progress tracking your scroll. The mock below shows what the markup represents.

Import

import 'motion-components/motion-progress'   // just this one
import 'motion-components'               // or the whole library

Usage

<!-- Document scroll progress, top of viewport -->
<motion-progress thickness="3" style="--mc-progress-color: #60a5fa"></motion-progress>

<!-- Per-element progress, bottom of viewport -->
<motion-progress
  target="#article"
  position="bottom" style="--mc-progress-color: currentColor"
></motion-progress>

Per-element progress

Pass a CSS selector to target to track scroll progress through a specific element rather than the whole document. Useful for long-form articles, sticky sections, or per-card readers.

Properties

Attribute Property Type Default Description
position position string 'top' Edge of the viewport the bar pins to: 'top' or 'bottom'
thickness thickness number 3 Bar thickness in pixels
target target string '' CSS selector of the scroll target. Defaults to the document
bounce bounce number 0.15 Spring bounciness applied to the scaleX response
duration duration number 0.4 Spring duration of the scaleX response, in seconds

CSS custom properties

Property Type Default Description
--mc-progress-color color var(--mc-color-accent, #2563eb) Bar color

JavaScript API

Control the progress indicator programmatically with play(), pause(), finish(), and cancel(). The instance below pins an amber bar to the bottom edge of the viewport (the top bar is this page's own progress).

Look at the bottom of the viewport. Scroll while playing to see the bar track, then try the transport controls.

playState: –

Accessibility

The bar is decorative and rendered with aria-hidden="true", so screen readers skip it. It does not steal focus or pointer events. Spring overshoot is deliberately small; if you need a perfectly linear bar, set bounce="0".