Tiny scroll progress bar for long posts

December 2, 2025

Tiny Reading Progress Bar for Long Posts

This tiny snippet adds a slim “reading progress” bar at the top of the viewport for long posts. As the visitor scrolls down, the bar fills from left to right. It’s a small UX touch that helps people feel oriented on long articles and know how much is left without hunting for the scrollbar.

Because it’s just a single fixed bar and a short script, it works well on blogs, documentation pages, tutorials, and long-form landing pages. There are no external dependencies and it stays out of the way of your layout and content.

Copy-paste snippet (CSS, HTML & JavaScript)

The snippet below includes the styles, the progress bar markup, and a tiny script that keeps everything in sync as the user scrolls:

<style>
  /* Tiny scroll progress bar for long posts */

  /* Container bar fixed at the top */
  #vibe-scroll-progress {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 3px;              /* make it taller if you want */
    background: rgba(0, 0, 0, 0.05);
    z-index: 9999;
    pointer-events: none;     /* don’t block clicks */
  }

  /* The filling part */
  #vibe-scroll-progress-inner {
    width: 0%;
    height: 100%;
    background: linear-gradient(90deg, #A829A7, #000);
    transform-origin: left center;
    transition: width 0.08s linear;
  }

  /* Optional: add a small offset to your layout’s top spacing if needed */
  body {
    padding-top: 3px; /* match the bar height if your header is flush to the top */
  }
</style>

<!-- Place this near the top of your <body> -->
<div id="vibe-scroll-progress">
  <div id="vibe-scroll-progress-inner"></div>
</div>

<script>
  (function () {
    var outer = document.getElementById('vibe-scroll-progress');
    var inner = document.getElementById('vibe-scroll-progress-inner');

    if (!outer || !inner) {
      return; // element missing, nothing to do
    }

    function updateScrollProgress() {
      var doc = document.documentElement;
      var body = document.body;

      // How far we’ve scrolled
      var scrollTop = doc.scrollTop || body.scrollTop || 0;

      // Total scrollable distance
      var scrollHeight = (doc.scrollHeight || body.scrollHeight || 0) - doc.clientHeight;

      if (scrollHeight <= 0) {
        inner.style.width = '0%';
        return;
      }

      var progress = (scrollTop / scrollHeight) * 100;

      // Clamp between 0 and 100
      if (progress < 0) progress = 0;
      if (progress > 100) progress = 100;

      inner.style.width = progress.toFixed(2) + '%';
    }

    // Run on load + scroll + resize
    window.addEventListener('scroll', updateScrollProgress, { passive: true });
    window.addEventListener('resize', updateScrollProgress);
    document.addEventListener('DOMContentLoaded', updateScrollProgress);

    // Initial call in case the page is short or already scrolled
    updateScrollProgress();
  })();
</script>

How to use it

Drop the <style> block and the <div id="vibe-scroll-progress"> markup into your layout (usually near the top of <body>) and paste the JavaScript just before your closing </body>. Once it’s in place, any long page that uses that layout will automatically show the progress bar as people scroll.

By default, it:

  • Sticks a 3px bar to the top of the viewport.
  • Fills the inner bar from 0% to 100% based on scroll position.
  • Listens to scroll and resize so it stays accurate.
  • Uses pointer-events: none so it never blocks clicks or links.

If you don’t want the extra top padding, you can remove the body { padding-top: 3px; } rule or adjust it to match your existing header height. The bar is fixed and doesn’t replace your navigation; it simply sits above it.

Customizing the look

You can tweak a few easy knobs to better match your design:

  • Height: change height: 3px; to 2px or 4px (or more) if you want a thinner or thicker bar.
  • Colors: swap the linear-gradient for a solid color like #000, or use your brand colors for the fill.
  • Position: move top: 0; to bottom: 0; if you’d rather show the progress at the bottom of the viewport.
  • Animation feel: adjust transition: width 0.08s linear; for a snappier or smoother fill effect.

Where it works best

This pattern shines on pages where visitors scroll through a lot of content and want a quick sense of “how far along” they are. Good candidates include:

  • Long guides and tutorials.
  • Docs pages with multiple sections.
  • Case studies and long-form sales pages.
  • Any article where you want to give a subtle progress cue.

Because it’s just a single fixed bar and a couple of event listeners, it’s light enough for everyday use and doesn’t feel like a heavy plugin. You keep full control over the styles and behavior, and you can remove it anytime by taking out the snippet.

Comments (0)

No comments yet — be the first.

← Back to all scripts