もくじ
通常、スクロールバーのデザインはCSSでしか変更できませんが、JavaScriptを使えば「完全自作のスクロールバー」を実現できます。
本記事では、標準スクロールバーを非表示にしてホバー時に表示・ドラッグで操作できるカスタムスクロールバー、スマホでも動作するカスタムスクロールバーをゼロから実装する方法を解説します。
スクロールバーをCSSでカスタマイズする方法は以下の記事で紹介しています。
-

【CSS】スクロールバーのデザインをカスタマイズする方法
もくじスクロールバーをカスタマイズできるブラウザ基本的なカスタマイズ方法(Chrome / Edge / Safari)Firefoxでのカスタマイズ方法クロスブラウザ対応の書き方ダークモード+ホバー ...
JavaScriptでスクロールバーを自作するメリット
通常のスクロールバーはブラウザやOSによってデザインが異なり、サイト全体の統一感を損なうことがあります。
JavaScriptでスクロールバーを自作すると、以下のようなメリットがあります。
- サイトデザインに合わせて完全カスタマイズ可能
- ホバー表示やアニメーションにも対応
- ドラッグ・タッチ操作など、より自然な操作感を再現できる
完成イメージ
- 標準スクロールバーは非表示
- マウスホバーでフェードイン
- つまみ(thumb)をドラッグで操作可能
- スマホでも指で動かせる
【サンプル】自作スクロールバー
自作スクロールバーのデモです。
このように、スクロールコンテナの中に多くのテキストを入れると...
下に進むとスクロールバーが機能します。
ホバーするとスクロールバーが表示されます。
さらに、つまみをドラッグして操作も可能です。
スマホでも指で動かせます。
【実装コード】自作スクロールバーを実装する
HTMLの基本構造
Copyをクリックするとコピーできます。
<div class="scroll-container"> <div class="scroll-content"> <p>自作スクロールバーのデモです。</p> <p>このように、スクロールコンテナの中に多くのテキストを入れると...</p> <p>下に進むとスクロールバーが機能します。</p> <p>ホバーするとスクロールバーが表示されます。</p> <p>さらに、つまみをドラッグして操作も可能です。</p> <p>スマホでも指で動かせます。</p> </div> <div class="custom-scrollbar"> <div class="custom-thumb"></div> </div></div>CSSでデザインを整える
Copyをクリックするとコピーできます。
.scroll-container { position: relative; width: 100%; max-width: 300px; height: 200px; padding: 10px; overflow: hidden; /* 標準スクロールバーを非表示 */ border: 1px solid #ccc; border-radius: 6px;}.scroll-content { height: 100%; overflow-y: scroll; padding-right: 20px; /* カスタムバー分の余白 */ scrollbar-width: none; /* Firefoxで非表示 */}.scroll-content::-webkit-scrollbar { display: none; /* Chrome/Safariで非表示 */}.custom-scrollbar { position: absolute; top: 0; right: 2px; width: 6px; height: 100%; background: rgba(0, 0, 0, 0.05); opacity: 0; transition: opacity 0.3s; pointer-events: none;}/* ホバーでフェードイン */.scroll-container:hover .custom-scrollbar { opacity: 1; pointer-events: auto;}.custom-thumb { position: absolute; top: 0; width: 100%; height: 40px; background: #666; border-radius: 3px; transition: background 0.2s; cursor: grab;}.custom-thumb:hover { background: #444;}/* スマホでは常時表示(hoverが使えないため) */@media (hover: none) and (pointer: coarse) { .custom-scrollbar { opacity: 1; pointer-events: auto; }}JavaScriptでスクロールを制御(PC版)
PCで動作させるための基本コードは以下の通りです。
Copyをクリックするとコピーできます。
document.addEventListener('DOMContentLoaded', function() { const container = document.querySelector('.scroll-container'); const content = container.querySelector('.scroll-content'); const scrollbar = container.querySelector('.custom-scrollbar'); const thumb = scrollbar.querySelector('.custom-thumb'); function updateThumb() { const ratio = container.clientHeight / content.scrollHeight; const thumbHeight = Math.max(ratio * container.clientHeight, 30); thumb.style.height = thumbHeight + 'px'; const scrollTopRatio = content.scrollTop / (content.scrollHeight - container.clientHeight); thumb.style.top = scrollTopRatio * (container.clientHeight - thumbHeight) + 'px'; } content.addEventListener('scroll', updateThumb); window.addEventListener('resize', updateThumb); updateThumb();});JavaScriptでスクロールを制御(スマホ対応)
スマホではmousedownやmousemoveが使えないため、touchstart,touchmove,touchendを追加します。
Copyをクリックするとコピーできます。
document.addEventListener('DOMContentLoaded', function() { const container = document.querySelector('.scroll-container'); const content = container.querySelector('.scroll-content'); const scrollbar = container.querySelector('.custom-scrollbar'); const thumb = scrollbar.querySelector('.custom-thumb'); function updateThumb() { const ratio = container.clientHeight / content.scrollHeight; const thumbHeight = Math.max(ratio * container.clientHeight, 30); thumb.style.height = thumbHeight + 'px'; const scrollTopRatio = content.scrollTop / (content.scrollHeight - container.clientHeight); thumb.style.top = scrollTopRatio * (container.clientHeight - thumbHeight) + 'px'; } content.addEventListener('scroll', updateThumb); window.addEventListener('resize', updateThumb); updateThumb(); let isDragging = false; let startY, startScrollTop; function startDrag(clientY) { isDragging = true; startY = clientY; startScrollTop = content.scrollTop; thumb.style.cursor = 'grabbing'; document.body.style.userSelect = 'none'; } function moveDrag(clientY) { if (!isDragging) return; const deltaY = clientY - startY; const scrollRatio = (content.scrollHeight - container.clientHeight) / (container.clientHeight - thumb.clientHeight); content.scrollTop = startScrollTop + deltaY * scrollRatio; } function endDrag() { isDragging = false; thumb.style.cursor = 'grab'; document.body.style.userSelect = ''; } // --- マウス操作 --- thumb.addEventListener('mousedown', e => startDrag(e.clientY)); document.addEventListener('mousemove', e => moveDrag(e.clientY)); document.addEventListener('mouseup', endDrag); // --- タッチ操作(スマホ対応) --- thumb.addEventListener('touchstart', e => startDrag(e.touches[0].clientY)); document.addEventListener('touchmove', e => moveDrag(e.touches[0].clientY)); document.addEventListener('touchend', endDrag);});スマホ対応のポイント
| 課題 | 対策 |
|---|---|
| hoverが使えない | スマホでは.custom-scrollbarを常時表示 |
| マウスイベントが無効 | touchstart,touchmove,touchendを追加 |
| スクロール追従 | scrollイベントでthumb位置を更新 |
| スクロールの遅延 | スクロール領域をネイティブ処理に任せる |
仕組みの解説(ドラッグ操作とは?)
「ドラッグ操作」とは、つまみ(thumb)をマウスや指で掴んで動かし、それに応じてスクロールを制御する仕組みのことです。
| イベント | 内容 |
|---|---|
mousedown/touchstart | つまみを掴んでドラッグ開始 |
mousemove/touchmove | マウスまたは指の動きに合わせてスクロール量を更新 |
mouseup/touchend | 離してドラッグ終了 |
これにより、標準スクロールバーと同じ操作感を再現できます。
まとめ
JavaScriptを使えば、CSSでは制御できない完全自作のスクロールバーを実現できます。
本記事のポイント
- 標準スクロールバーを非表示にしてデザイン統一
- ホバー表示で視認性UP
- PC・スマホどちらでもドラッグ操作に対応
- CSS・JSのみで完結、ライブラリ不要
応用例
- 横方向スクロールにも対応可能
- スクロール位置に応じて色を変化
- スクロールアニメーションとの組み合わせ
今回のコードをベースに、あなたのWebデザインに合わせて自由に拡張してみてください。

