良く使うJSコード集

jQueryタブ切り替えサンプル集|シンプル・フェード・スライドアンダーライン・直リンク対応

更新日:2026-05-27 著者:unigram 読了目安:12分

この記事の要点

jQueryで作るタブ切り替えの4パターンをコピペ可能なコード付きで解説。シンプル・フェードアニメーション・スライドアンダーライン・ハッシュURL対応までプレビュー付き。

jQueryを使ったタブ切り替えは、商品説明・FAQ・プロフィールページなどでよく使われるUIです。

この記事では、シンプルな実装からフェード・スライドアニメーション・ハッシュURL対応まで、実務でそのまま使える4パターンをプレビュー+コード付きで解説します。

この記事でわかること

  • シンプルなタブ切り替え(data属性でパネルを紐付け)
  • フェードアニメーション付きタブ(opacity + transition)
  • アンダーラインがスライドするタブ(position() で位置を取得)
  • ハッシュURLで直リンク可能なタブ(history.pushState)

前提:jQueryの読み込み

この記事のサンプルはすべて jQuery 3.x を前提としています。HTMLの <head></body> 直前に以下を追加してください。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

01

シンプルなタブ切り替え

ボタンに data-target 属性でパネルのIDを指定し、クリック時に active クラスを付け替えるシンプルな実装。同一ページに複数設置しても独立して動作する。

data-target でパネルを紐付け.closest() で独立動作display: none / block で切り替え
Preview
タブ 1
タブ 2
タブ 3

タブ 1 のコンテンツ。クリックで切り替わります。

タブ 2 のコンテンツ。アニメーションなしのシンプルな切り替え。

タブ 3 のコンテンツ。追加・削除がしやすいシンプル構成。

HTMLCSSJS
index.htmlcopy
<div class="tab-wrap">
  <!-- タブボタン -->
  <div class="tab-list">
    <button class="tab-btn active" data-target="panel-1">タブ 1</button>
    <button class="tab-btn" data-target="panel-2">タブ 2</button>
    <button class="tab-btn" data-target="panel-3">タブ 3</button>
  </div>
  <!-- タブパネル -->
  <div class="tab-panel active" id="panel-1">
    <p>タブ 1 のコンテンツ</p>
  </div>
  <div class="tab-panel" id="panel-2">
    <p>タブ 2 のコンテンツ</p>
  </div>
  <div class="tab-panel" id="panel-3">
    <p>タブ 3 のコンテンツ</p>
  </div>
</div>
style.csscopy
/* ── タブボタン ── */
.tab-list {
  display: flex;
  gap: 4px;
  border-bottom: 2px solid #e4e2dd;
  margin-bottom: 0;
}
.tab-btn {
  padding: 10px 20px;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px; /* border-bottom と重ねて親のボーダーを上書き */
  cursor: pointer;
  font-size: 14px;
  color: #6b6b6b;
  transition: color .2s, border-color .2s;
}
.tab-btn.active {
  color: #3e8685;
  border-bottom-color: #3e8685;
  font-weight: 600;
}
/* ── タブパネル ── */
.tab-panel {
  display: none; /* デフォルトは非表示 */
  padding: 20px;
  background: #fff;
  border: 1px solid #e4e2dd;
  border-top: none;
  border-radius: 0 0 6px 6px;
}
.tab-panel.active {
  display: block; /* active クラスがついたパネルだけ表示 */
}
script.jscopy
$(function () {
  /* タブボタンをクリックしたとき */
  $('.tab-btn').on('click', function () {
    var target = $(this).data('target');
    /* 同じ .tab-wrap 内のボタン・パネルだけを操作する */
    var $wrap = $(this).closest('.tab-wrap');
    /* すべてのボタンとパネルから active を外す */
    $wrap.find('.tab-btn').removeClass('active');
    $wrap.find('.tab-panel').removeClass('active');
    /* クリックしたボタンと対応するパネルに active を付ける */
    $(this).addClass('active');
    $('#' + target).addClass('active');
  });
});
02

フェードアニメーション付きタブ

position: absolute で全パネルを重ね、opacitytransition でフェードする実装。display: none では CSS アニメーションが効かないため、opacity + pointer-events の組み合わせを使う。

opacity + transition でフェードposition: absolute で重ねるpointer-events: none で貫通
Preview
概要
仕様
よくある質問

フェードアニメーション付きのタブです。切り替え時に opacitytransition でなめらかに切り替わります。

仕様タブのコンテンツ。display: none ではなく opacity: 0 / 1 + position で実装するとフェードが効きます。

よくある質問のコンテンツ。商品ページ・ランディングページのタブによく使われる形式です。

HTMLCSSJS
index.htmlcopy
<div class="tab-wrap tab-fade">
  <div class="tab-list">
    <button class="tab-btn active" data-target="panel-1">概要</button>
    <button class="tab-btn" data-target="panel-2">仕様</button>
    <button class="tab-btn" data-target="panel-3">よくある質問</button>
  </div>
  <!-- パネルを position: relative のラッパーで囲む -->
  <div class="tab-panels-wrap">
    <div class="tab-panel active" id="panel-1">概要のコンテンツ</div>
    <div class="tab-panel" id="panel-2">仕様のコンテンツ</div>
    <div class="tab-panel" id="panel-3">よくある質問のコンテンツ</div>
  </div>
</div>
style.csscopy
/* ── フェード付きタブ ── */
.tab-panels-wrap {
  position: relative;
  min-height: 120px;
}
.tab-fade .tab-panel {
  position: absolute; /* 全パネルを重ねて配置する */
  top: 0; left: 0; right: 0;
  opacity: 0; /* デフォルトは透明 */
  pointer-events: none; /* 非表示中はクリックを貫通させる */
  transition: opacity .3s ease;
  padding: 20px;
  background: #fff;
}
.tab-fade .tab-panel.active {
  position: relative; /* active は通常フローに戻してラッパーの高さを決める */
  opacity: 1;
  pointer-events: auto;
}
script.jscopy
$(function () {
  /* フェード付きタブ(.tab-fade クラスを持つ場合) */
  $('.tab-fade .tab-btn').on('click', function () {
    var target = $(this).data('target');
    var $wrap = $(this).closest('.tab-wrap');
    /* ボタンの active を付け替える */
    $wrap.find('.tab-btn').removeClass('active');
    $(this).addClass('active');
    /* フェードアウト → フェードイン */
    $wrap.find('.tab-panel.active').removeClass('active');
    $('#' + target).addClass('active');
  });
});
03

アンダーラインがスライドするタブ

タブ切り替え時に下線が leftwidth のアニメーションでスライドするデザイン。position() でボタンの位置を取得し、$.css() で動的に下線を移動させる。

.position() でボタン位置を取得left / width を transition でアニメーション初期位置は $(function) 内で設定
Preview
すべて
Web制作
SEO
WordPress

すべてのコンテンツを表示します。フィルタリングタブにも応用できます。

Web制作カテゴリのコンテンツ。

SEOカテゴリのコンテンツ。

WordPressカテゴリのコンテンツ。

HTMLCSSJS
index.htmlcopy
<div class="tab-wrap">
  <!-- アンダーラインバーを含むタブリスト -->
  <div class="tab-list tab-underline">
    <button class="tab-btn active" data-target="panel-all">すべて</button>
    <button class="tab-btn" data-target="panel-web">Web制作</button>
    <button class="tab-btn" data-target="panel-seo">SEO</button>
    <!-- アンダーラインバー(JSで位置・幅を動かす) -->
    <div class="tab-underline-bar"></div>
  </div>
  <div class="tab-panel active" id="panel-all">すべて</div>
  <div class="tab-panel" id="panel-web">Web制作</div>
  <div class="tab-panel" id="panel-seo">SEO</div>
</div>
style.csscopy
.tab-underline {
  position: relative;
  border-bottom: 2px solid #e4e2dd;
}
.tab-underline .tab-btn {
  border-bottom: none; /* 個別の下線は非表示 */
  color: #6b6b6b;
}
.tab-underline .tab-btn.active {
  color: #3e8685;
  font-weight: 600;
}
/* スライドするアンダーライン */
.tab-underline-bar {
  position: absolute;
  bottom: -2px; /* 親の下ボーダーに重ねる */
  height: 2px;
  background: #3e8685;
  transition: left .25s ease, width .25s ease; /* 位置と幅をなめらかに動かす */
}
script.jscopy
$(function () {
  /* アンダーバーを active ボタンの位置・幅に合わせる */
  function moveBar($btn) {
    var $bar = $btn.closest('.tab-underline').find('.tab-underline-bar');
    $bar.css({
      left: $btn.position().left,  /* ボタンの左端位置 */
      width: $btn.outerWidth() /* ボタンの幅 */
    });
  }
  /* 初期位置を設定 */
  moveBar($('.tab-underline .tab-btn.active'));
  $('.tab-underline .tab-btn').on('click', function () {
    var target = $(this).data('target');
    var $wrap = $(this).closest('.tab-wrap');
    $wrap.find('.tab-btn').removeClass('active');
    $wrap.find('.tab-panel').removeClass('active');
    $(this).addClass('active');
    $('#' + target).addClass('active');
  moveBar($(this));
  });
});
04

ハッシュURLで直リンク可能なタブ

タブ切り替え時に history.pushState() でURLのハッシュを更新する。SNSシェアや外部から特定タブへ直接リンクが可能になる。ページ読み込み時に location.hash を確認してタブを自動で開く。

data-hash 属性にハッシュ値を設定history.pushState() でURL更新location.hash で初期タブを自動選択
Preview
プロフィール
実績
お問い合わせ

ハッシュURLに対応したタブです。URLの末尾が #tab-profile の形式になり、直接リンクが可能になります。

URLが #tab-works に変わります。ブラウザの戻るボタンでも前のタブに戻れます。

URLが #tab-contact に変わります。SNSで特定タブへの直リンが可能になります。

HTMLCSSJS
index.htmlcopy
<!-- data-hash 属性にURLのハッシュ値を設定 -->
<div class="tab-wrap">
  <div class="tab-list">
    <button class="tab-btn active" data-target="panel-profile" data-hash="tab-profile">プロフィール</button>
    <button class="tab-btn" data-target="panel-works" data-hash="tab-works">実績</button>
    <button class="tab-btn" data-target="panel-contact" data-hash="tab-contact">お問い合わせ</button>
  </div>
  <div class="tab-panel active" id="panel-profile">プロフィール内容</div>
  <div class="tab-panel" id="panel-works">実績内容</div>
  <div class="tab-panel" id="panel-contact">お問い合わせ内容</div>
</div>
style.csscopy
/* 基本スタイルはシンプルタブ(01)と同じ */
/* 追加CSSは不要 */
script.jscopy
$(function () {
  /* ハッシュ値でタブを開く共通関数 */
  function openTabByHash(hash) {
    $('.tab-btn[data-hash="' + hash + '"]').trigger('click');
  }
  /* ページ読み込み時にURLのハッシュを確認して該当タブを開く */
  if (location.hash) {
    var hash = location.hash.replace('#', '');
    openTabByHash(hash);
  }
  $('.tab-btn').on('click', function () {
    var target = $(this).data('target');
    var hash   = $(this).data('hash');
    var $wrap = $(this).closest('.tab-wrap');
    $wrap.find('.tab-btn').removeClass('active');
    $wrap.find('.tab-panel').removeClass('active');
    $(this).addClass('active');
    $('#' + target).addClass('active');
    /* URLにハッシュを付与(ページスクロールなし・履歴には残す) */
    if (hash) history.pushState(null, null, '#' + hash);
  });
});

まとめ

  • 基本構造は「ボタンの data-target = パネルの id」で紐付け
  • .closest() で同じ .tab-wrap 内だけ操作すれば複数設置に対応できる
  • フェードには display: none ではなく opacity + pointer-events を使う
  • スライドアンダーラインは .position() でボタン位置を取得して動かす
  • 直リンク対応は history.pushState()location.hash の組み合わせ

 

この記事を書いた人

unigram
web、印刷、映像などの制作をしています。@京都、フリーランス18年目。 大学で講師もしています。 自身の備忘録も兼ねて、Web制作・WordPress・SEO・GA4・生成AI活用をテーマに情報発信しています。わかりやすく優しい内容で記事作成を心がけています。