Reading progress bar

A thin bar at the top fills from 0 to 100% as the article scrolls, driven by scroll position.

ScrollScroll progress CSS scroll-timelineGSAP scroll-progress-based Targets: Web Chrome/Edge 115+, Safari 26+, Firefox behind flag (~88%); JS fallback included
Scroll inside the frame ↕
Target
Implement the "Reading progress bar" effect in vanilla HTML/CSS/JS.

Context: A thin bar at the top fills from 0 to 100% as the article scrolls, driven by scroll position.
Trigger: the page scrolls; progress is bound to scroll position, not time.
Timeline: scroll-progress-based (map scroll position to animation progress; no fixed duration).

Motion tokens (normal):
- scaleX: 0 → 1
- scroll range: 0% (top of scroller) → 100% (bottom of scroller)
- easing: linear
- note: transform-origin left; bar height 3px

Motion tokens (prefers-reduced-motion):
- scaleX: 0 → 1
- scroll range: 0% → 100%
- easing: linear
- note: scroll-bound motion is user-driven, so it stays; only remove any smoothing

Technique: prefer CSS `animation-timeline: scroll()/view()` inside `@supports (animation-timeline: scroll())`, with a JS fallback; GSAP (ScrollTrigger where relevant) is acceptable as an alternative.

Acceptance:
- animate only transform and opacity unless the spec lists other properties
- no layout shift; content is visible without the animation
- when prefers-reduced-motion is set, use the reduced tokens only
- bar uses transform: scaleX, never width
- works when the scroller is a nested element, not only the document

Generated from the spec. Prompts differ by target name only; the tokens are the source of truth.