KH-WEBLOG TOP > WEBメモ > JavaScript > 横スクロール比較表に「常時表示スクロールバー」を実装する方法:javascript

横スクロール比較表に「常時表示スクロールバー」を実装する方法:javascript

比較表のように列数が多い表をレスポンシブ対応させると、横スクロールが必須になります。
通常のブラウザのスクロールバーは、macOSのトラックパッド環境などでは「操作している時だけ表示」される仕様になっており、ユーザーが「まだ右にスクロールできる」ことに気づきにくいという問題があります。

この記事では、ネイティブのスクロールバーに頼らず、常に表示される自作のスクロールバーをHTML・CSS・JavaScriptだけで実装する方法を紹介します。

コーディング・WordPress化作業を代行します

完成イメージ

  • 表の上に、常に見えるスクロールバー(トラック+つまみ)を配置
  • つまみをドラッグして表をスクロールできる
  • スマホではスワイプ操作にもそのまま対応
  • 表の1列目(項目名)はstickyで固定し、スクロールしても見出しが常に見える

HTMLの構成

自作スクロールバー用のdivと、表を囲うスクロールエリアを用意します。

<!-- 自作スクロールバー -->
<div class="custom-scrollbar">
  <div class="custom-scrollbar-track" id="scrollTrack">
    <div class="custom-scrollbar-thumb" id="scrollThumb"></div>
  </div>
</div>

<!-- 本体テーブル -->
<div class="table-scroll" id="tableScroll">
  <table class="compare-table" id="compareTable">
    ...
  </table>
</div>

CSSのポイント:ネイティブのスクロールバーを消す

まず、表側のスクロールエリアからブラウザ標準のスクロールバーを見えなくします。overflow-x: auto自体は残すので、スクロール機能そのものは生きたままです。

.table-scroll{
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;      /* Firefox */
  -ms-overflow-style: none;   /* 古いEdge */
  -webkit-overflow-scrolling: touch; /* iOSの慣性スクロールを滑らかに */
}
.table-scroll::-webkit-scrollbar{
  display: none;              /* Chrome/Safari */
}

その代わりに、自作のトラックとつまみにデザインを当てます。

.custom-scrollbar-track{
  position: relative;
  height: 10px;
  background: #e6edf4;
  border-radius: 5px;
  cursor: pointer;
}
.custom-scrollbar-thumb{
  position: absolute;
  top: 0;
  left: 0;
  height: 10px;
  background: #5b8dc2;
  border-radius: 5px;
  cursor: grab;
}

JavaScriptのポイント①:つまみの幅と位置を計算する

つまみの幅は「表示中の幅 ÷ コンテンツ全体の幅」の比率から算出します。列数が多いほどこの比率は小さくなり、つまみも短くなります。

const MIN_THUMB_WIDTH = 30;    // 最小幅
const MAX_THUMB_WIDTH = 120;   // 最大幅
const THUMB_WIDTH_SCALE = 0.5; // 比率に掛ける倍率

function updateThumb() {
  const trackWidth = scrollTrack.clientWidth;
  const contentWidth = table.scrollWidth;
  const visibleWidth = tableScroll.clientWidth;

  const ratio = visibleWidth / contentWidth;
  const rawWidth = trackWidth * ratio * THUMB_WIDTH_SCALE;
  const thumbWidth = Math.min(Math.max(rawWidth, MIN_THUMB_WIDTH), MAX_THUMB_WIDTH);

  const maxScrollLeft = table.scrollWidth - tableScroll.clientWidth;
  const maxThumbLeft = trackWidth - thumbWidth;
  const scrollRatio = maxScrollLeft > 0 ? tableScroll.scrollLeft / maxScrollLeft : 0;

  scrollThumb.style.width = thumbWidth + 'px';
  scrollThumb.style.left = (scrollRatio * maxThumbLeft) + 'px';
}

THUMB_WIDTH_SCALEを小さくするとつまみが短くなり、MIN_THUMB_WIDTH・MAX_THUMB_WIDTHでその上限・下限を制御できます。デザインに合わせて数値を調整するだけなので、CSSに直接widthを書くより柔軟に扱えます。

JavaScriptのポイント②:ドラッグとスワイプに対応する

つまみはmousedown/touchstartでドラッグ開始、mousemove/touchmoveで移動量に応じてscrollLeftを書き換え、mouseup/touchendで終了します。マウスとタッチの両方に同じロジックを使い回せるよう、startDrag / moveDrag / endDragという共通関数にまとめています。

scrollThumb.addEventListener('mousedown', e => startDrag(e.clientX));
document.addEventListener('mousemove', e => moveDrag(e.clientX));
document.addEventListener('mouseup', endDrag);

scrollThumb.addEventListener('touchstart', e => startDrag(e.touches[0].clientX), { passive: true });
document.addEventListener('touchmove', e => moveDrag(e.touches[0].clientX), { passive: true });
document.addEventListener('touchend', endDrag);

なお、表自体はoverflow-x: autoのままなので、スクロールバーが非表示でも、スマホでは表の中身を直接スワイプするだけで普通にスクロールできます。自作スクロールバーはあくまで「見た目のガイド兼、もう一つの操作手段」という位置づけです。

まとめ

  • ネイティブのスクロールバーはOSやブラウザの設定に表示が左右されやすい
  • ::-webkit-scrollbar { display: none } + 自作のトラック・つまみdivに置き換えることで、常時表示・自由なデザインが可能になる
  • つまみの幅は固定値ではなく比率計算にしておくと、列数が変わっても自動で調整される
  • マウスのドラッグとスマホのスワイプ、両方に対応させることでどの環境でも同じ操作感になる

完成コード

<!-- 自作スクロールバー(常時表示・本体テーブルと同期) -->
  <div class="custom-scrollbar">
    <div class="custom-scrollbar-track" id="scrollTrack">
      <div class="custom-scrollbar-thumb" id="scrollThumb"></div>
    </div>
  </div>

  <!-- 本体テーブル -->
  <div class="table-scroll" id="tableScroll">
    <table class="compare-table" id="compareTable">
      <thead>
        <tr>
          <th class="row-label">製品名</th>
          <th class="product-head">サンプル製品A</th>
          <th class="product-head">サンプル製品B</th>
          <th class="product-head">サンプル製品C</th>
          <th class="product-head">サンプル製品D</th>
          <th class="product-head">サンプル製品E</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td class="row-label">メーカー</td>
          <td class="data-cell">ダミー株式会社</td>
          <td class="data-cell">ダミー株式会社</td>
          <td class="data-cell">サンプル工業</td>
          <td class="data-cell">サンプル工業</td>
          <td class="data-cell">テスト商事</td>
        </tr>
      </tbody>
    </table>
  </div>

ロジック部分はそのままコピーして使えるので、表の列数やデータに合わせて<table>部分だけ差し替えて利用できます。

コーディング・WordPress化作業を代行します

JavaScriptのおすすめ参考書

楽天ブックス
¥2,838 (2026/06/25 16:17時点 | 楽天市場調べ)

TAGS

.htaccess ActionScript All in one seo pack Contact Form 7 CSS CSS3 EC-CUBE Flash HTML HTML5 JavaScript jQuery LightBox PHP RSS SEO WordPress アイキャッチ画像 アクセス解析 カスタムフィールド カテゴリー カラーミーショップ カート コメント ショートコード テンプレートタグ ドロップダウンメニュー パーマリンク フォーム フルスクリーン ブログカード プラグイン ページテンプレート ページナビ ページ分割 マウスイベント リダイレクト リンク リンクカード レンタルサーバー ロールオーバー 携帯サイト 条件分岐 正規表現 関連記事