← Demo hub

Reading progress bar

Try: Scroll down—the thin bar at the top fills with document scroll. No scroll listeners or Vue state: use scroll-driven animation with animation-timeline: scroll(root block).

If the bar never moves, your browser may not support scroll timelines yet. Pair with prefers-reduced-motion in production.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris.

Pellentesque pretium lectus id turpis. Maecenas sollicitudin. Fusce suscipit libero eget elit. Praesent vitae arcu tempor neque lacinia pretium.

Integer in mauris eu nibh euismod gravida. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo.

Source

<div class="read-progress" aria-hidden="true"></div>

.read-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  transform-origin: 0 50%;
  transform: scaleX(0);
}
@supports (animation-timeline: scroll(root block)) {
  .read-progress {
    animation: read-progress linear forwards;
    animation-timeline: scroll(root block);
  }
}
@keyframes read-progress {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}
Support: Scroll timelines are strongest in Chromium; verify Safari/Firefox. Wrap in @supports (animation-timeline: scroll(root block)) if you need a non-animated fallback.