スクロールプログレスバーとは

画面上部に固定した細いバーが、ページを読み進めた分だけ伸びていく、スクロール量を可視化する UI。

概要

画面の最上部に固定した細いバーが、ページ全体のうちどこまでスクロールしたかに応じて左から右へ伸びていく UI です。 長い記事でどれくらい読み進めたかを視覚的に伝える「読了バー」として使われます。 CSS だけで作れる animation-timeline: scroll() という新しい仕組みと、対応していないブラウザ向けに scroll イベントで幅を更新する JavaScript 版の両方がよく使われます。

別名

表記ゆれ:スクロールプログレスバー、読了バー、読み進めバー

AI への伝え方

「ページ上部にスクロール量に応じて伸びるバーを付けて」で伝わります。 animation-timeline: scroll() は対応していないブラウザがあるため、「対応していない場合は JavaScript でフォールバックして」と伝えると安全です。

似たパーツとの違い

「プログレスバー」は処理の進み具合など決まった値の進捗を表す部品全般を指しますが、スクロールプログレスバーはその値元をスクロール量に限定した使い方のひとつです。

デモ

コード

HTML
<div class="scrollprogress-demo">
  <div class="scrollprogress-demo__bar" data-scrollprogress-bar></div>
  <article class="scrollprogress-demo__article">
    <h2>読了バーのデモ</h2>
    <p>下にスクロールすると、上部のバーが読み進めた分だけ伸びていきます。</p>
    <p>ダミーの本文です。ダミーの本文です。ダミーの本文です。ダミーの本文です。ダミーの本文です。</p>
    <p>ダミーの本文です。ダミーの本文です。ダミーの本文です。ダミーの本文です。ダミーの本文です。</p>
    <p>ダミーの本文です。ダミーの本文です。ダミーの本文です。ダミーの本文です。ダミーの本文です。</p>
    <p>ダミーの本文です。ダミーの本文です。ダミーの本文です。ダミーの本文です。ダミーの本文です。</p>
    <p>ダミーの本文です。ダミーの本文です。ダミーの本文です。ダミーの本文です。ダミーの本文です。</p>
    <p>ダミーの本文です。ダミーの本文です。ダミーの本文です。ダミーの本文です。ダミーの本文です。</p>
    <p>ここまでスクロールすると、バーは右端まで伸びます。</p>
  </article>
</div>
CSS
.scrollprogress-demo {
  font-family: sans-serif;
  color: #333333;
}

.scrollprogress-demo__bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 0%;
  height: 4px;
  background: #0017c1;
  z-index: 10;
  transform-origin: left;
}

/* animation-timeline: scroll() に対応する環境では、CSS だけでバーを伸ばす */
@supports (animation-timeline: scroll()) {
  .scrollprogress-demo__bar {
    width: 100%;
    transform: scaleX(0);
    animation: scrollprogress-demo-grow auto linear;
    animation-timeline: scroll(root);
  }
}

@keyframes scrollprogress-demo-grow {
  to {
    transform: scaleX(1);
  }
}

.scrollprogress-demo__article {
  padding: 24px;
  max-width: 480px;
}

.scrollprogress-demo__article h2 {
  margin-top: 0;
}
JS
// animation-timeline: scroll() に対応していない環境向けの JavaScript フォールバック
const supportsScrollTimeline = CSS.supports("animation-timeline: scroll()");

if (!supportsScrollTimeline) {
  const bar = document.querySelector("[data-scrollprogress-bar]");

  const updateProgress = () => {
    const scrollTop = document.documentElement.scrollTop;
    const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
    const ratio = scrollHeight > 0 ? scrollTop / scrollHeight : 0;
    if (bar) bar.style.width = `${Math.min(1, Math.max(0, ratio)) * 100}%`;
  };

  document.addEventListener("scroll", updateProgress, { passive: true });
  updateProgress();
}