【jQuery】ボタンクリックで要素の表示・非表示を切り替える完全ガイド|toggle・アニメーション・クラス・アクセシビリティまで

jQueryでボタンクリック時に要素を表示・非表示にするには複数の方法があります。シンプルな toggle() から、スライド・フェードアニメーション付き、CSSクラスで制御する方法、アクセシビリティ対応まで用途に合った実装パターンを体系的に解説します。

この記事でわかること

  • toggle() / show() / hide() の基本パターン
  • slideToggle() / fadeToggle() でアニメーション付き切り替え
  • CSSクラスで表示・非表示を管理する(パフォーマンス最適)
  • ボタンのテキストを「表示」↔「非表示」と連動させる
  • 複数要素の一括切り替え・グループ排他切り替え
  • aria-expanded属性でアクセシビリティ対応する
スポンサーリンク

toggle()で表示・非表示を切り替える(最もシンプル)

toggle() は要素が表示中なら非表示に、非表示なら表示に自動的に切り替えます。最もシンプルな実装です。

<button id="toggle-btn">詳細を表示/非表示</button>
<div id="detail-box">
  <p>ここに詳細コンテンツが入ります。</p>
</div>
$(function () {
  $('#toggle-btn').on('click', function () {
    $('#detail-box').toggle();
  });
});
toggle()はdisplay:noneで表示・非表示を制御する
toggle() は内部的に display:none の付与と除去で制御します。要素の元の display 値(block / inline-block / flex など)は自動的に保持されます。CSSで display:none を初期状態にしておくと、ページ読み込み時は非表示から始まります。

show() / hide()で表示状態を明示的に制御する

表示と非表示を別々のボタンで制御したい場合や、条件分岐で「必ず表示する」「必ず非表示にする」を明示したい場合に使います。

$(function () {
  // 表示・非表示を条件で切り替える
  $('#show-btn').on('click', function () {
    $('#panel').show();
  });
  $('#hide-btn').on('click', function () {
    $('#panel').hide();
  });

  // is(':visible')で現在の状態を確認してから制御
  $('#toggle-btn').on('click', function () {
    var $panel = $('#panel');
    if ($panel.is(':visible')) {
      $panel.hide();
    } else {
      $panel.show();
    }
  });
});
is(“:visible”)で表示状態を確認する
:visible セレクターは display:none でも visibility:hidden でも画面上に実際に表示されているかどうかを判定します。CSSで非表示にした要素も is(":visible") で正しく判定できます。

slideToggle() / fadeToggle()でアニメーション付き切り替え

突然表示・非表示が切り替わると視覚的に違和感があります。アニメーションを加えることでUXが大幅に向上します。

slideToggle():上下にスライドしながら切り替える

$(function () {
  $('#slide-btn').on('click', function () {
    $('#slide-panel').slideToggle(300);  // 300ms でスライド
  });
});

fadeToggle():フェードイン/フェードアウトで切り替える

$(function () {
  $('#fade-btn').on('click', function () {
    $('#fade-panel').fadeToggle(400);  // 400ms でフェード
  });
});

連打対策:stop()でアニメーションキューをクリアする

$(function () {
  $('#slide-btn').on('click', function () {
    // stop(true, true): 前のアニメーションをキャンセルして即完了させる
    $('#slide-panel').stop(true, true).slideToggle(300);
  });
});
連打するとアニメーションが積み重なる問題
ボタンを素早く何度もクリックするとslideToggle/fadeToggleが積み重なり、表示状態がずれていきます。stop(true, true) を前に付けることで前のアニメーションをキャンセルしてから新しいアニメーションを開始します。アニメーション全般の詳細はアニメーション完全ガイドを参照してください。

CSSクラスで表示・非表示を管理する

CSSのトランジションを活用したい場合や、パフォーマンスを重視する場合はjQueryでクラスを付与・削除してCSSで表示制御する方法が効果的です。

.panel {
  overflow: hidden;
  max-height: 500px;
  opacity: 1;
  transition: max-height 0.3s ease, opacity 0.3s ease;
}
.panel.is-hidden {
  max-height: 0;
  opacity: 0;
}
$(function () {
  // 初期状態を非表示にしたい場合はHTMLにis-hiddenクラスを付けておく
  $('#class-btn').on('click', function () {
    $('#class-panel').toggleClass('is-hidden');
  });
});
CSSクラス方式のメリット
CSS transition はGPUで処理されjQueryアニメーションよりパフォーマンスが高いです。特にモバイル端末や大量の要素がある場合に有利です。ただし display:none ↔ block はトランジションが効かないため、max-heightopacity でフェードを実現します。クラス操作の詳細はaddClass/removeClass/toggleClass完全ガイドを参照してください。

ボタンのテキストを「表示」↔「非表示」と連動させる

ボタンのラベルを表示状態に合わせて変えることで、ユーザーが次のアクションを直感的に理解できます。

$(function () {
  $('#toggle-btn').on('click', function () {
    var $panel = $('#panel');
    var $btn   = $(this);

    $panel.slideToggle(300, function () {
      // アニメーション完了後にボタンテキストを切り替え
      if ($panel.is(':visible')) {
        $btn.text('▲ 閉じる');
      } else {
        $btn.text('▼ 詳細を見る');
      }
    });
  });
});

複数要素の一括切り替えと排他制御(タブ風切り替え)

複数のパネルがあり、1つを開くと他が閉じる「排他切り替え(アコーディオン風)」のパターンです。

<div class="toggle-group">
  <button class="group-btn" data-target="#panel-a">パネルA</button>
  <button class="group-btn" data-target="#panel-b">パネルB</button>
  <button class="group-btn" data-target="#panel-c">パネルC</button>
</div>
<div id="panel-a" class="group-panel">パネルAのコンテンツ</div>
<div id="panel-b" class="group-panel" style="display:none;">パネルBのコンテンツ</div>
<div id="panel-c" class="group-panel" style="display:none;">パネルCのコンテンツ</div>
$(function () {
  $('.group-btn').on('click', function () {
    var target = $(this).data('target');
    var $target = $(target);

    if ($target.is(':visible')) {
      // すでに開いているパネルをクリック → 閉じる
      $target.slideUp(250);
    } else {
      // 他のパネルを閉じてから対象パネルを開く(排他制御)
      $('.group-panel').not($target).slideUp(250);
      $target.slideDown(250);
    }
  });
});
より高機能なアコーディオンが必要な場合
FAQ形式のアコーディオン・ネスト・アイコン連動・アクセシビリティ完全対応が必要な場合は、アコーディオン実装完全ガイドを参照してください。

aria-expanded属性でアクセシビリティ対応する

スクリーンリーダーのユーザーが「このボタンを押すと何が起きるか」を理解できるよう、aria-expanded 属性を設定します。

<button id="acc-btn" aria-expanded="false" aria-controls="acc-panel">
  詳細を見る
</button>
<div id="acc-panel" hidden>
  <p>詳細コンテンツです。</p>
</div>
$(function () {
  $('#acc-btn').on('click', function () {
    var $btn   = $(this);
    var $panel = $('#acc-panel');
    var expanded = $btn.attr('aria-expanded') === 'true';

    // aria-expandedを更新
    $btn.attr('aria-expanded', !expanded);

    // hidden属性とアニメーションを組み合わせる
    if (expanded) {
      $panel.slideUp(300, function () {
        $(this).attr('hidden', true);
      });
    } else {
      $panel.removeAttr('hidden').hide().slideDown(300);
    }
  });
});
aria-expanded・hidden属性・アニメーションの組み合わせ
hidden属性を設定するタイミングはslideUpのコールバック(完了後)にします。アニメーション開始時にhiddenを付けるとslideUpが効かなくなるためです。反対に表示するときは removeAttr("hidden") してから hide().slideDown() で「hiddenなし・display:none → slideDown」の順にします。

方法の比較と使い分け

方法 アニメーション パフォーマンス 向いている用途
toggle() なし(瞬時) 高い シンプルな表示切り替え
show() / hide() なし(瞬時) 高い 条件分岐で表示状態を制御
slideToggle() 上下スライド 普通 アコーディオン・FAQ
fadeToggle() フェード 普通 通知・モーダル・ヒント
CSSクラス + transition CSSで自由に設定 最も高い(GPU) スマホ重視・大量要素・カスタムアニメーション

まとめ

jQueryでボタンクリックによる表示・非表示切り替えを実装する際のポイントは次の通りです。

  • シンプルな切り替えには toggle()、明示的な制御には show()/hide()
  • アニメーションが必要なら slideToggle()/fadeToggle() + stop(true, true) で連打対策
  • パフォーマンスを重視するならCSSクラス + transition の組み合わせ
  • アクセシビリティのために aria-expanded 属性を更新する
  • ボタンのテキストも表示状態に合わせて変えるとUXが向上する

関連記事: addClass/removeClass/toggleClass完全ガイド / アニメーション完全ガイド / アコーディオン実装完全ガイド / 指定した条件で要素を表示・非表示にする

よくある質問(FAQ)

Qtoggle()で切り替えた後、表示状態がずれることがあります。
Aボタンを素早く連打するとアニメーションが積み重なり、状態がずれます。slideToggle()/fadeToggle() を使っている場合は前に stop(true, true) を付けてください。toggle()(アニメーションなし)では発生しません。
QCSSでdisplay:noneにした要素がtoggle()で表示されません。
ACSSのスタイルシートで display:none を設定した場合、jQueryはその要素を「表示できる元のdisplay値がわからない」と判断することがあります。HTMLの style="display:none" または $(el).hide() で非表示にした場合は正しく動作します。CSSで非表示にしたい場合はクラスを付与・削除する方法を使ってください。
QslideToggle()がアニメーションせず瞬時に切り替わります。
A要素に height:auto 以外のCSSが設定されているか、親要素の overflow:hidden が干渉している可能性があります。また position:absolute の要素はslideToggleが効かないことがあります。DevToolsでCSSを確認し、干渉する設定を取り除いてください。
Qページ読み込み時に要素を非表示にしたいですが、一瞬表示されてしまいます。
AHTMLに style="display:none" を直接書くか、CSSで .panel { display: none; } を指定することで、ページ読み込み時から非表示になります。$(function(){...}) 内で .hide() を呼ぶ方法はJavaScript実行まで一瞬表示されます(FOUC)。
Q動的に追加した要素のトグルボタンが動きません。
AAjaxなどで動的に追加した要素には $(selector).on("click", fn) でイベントを直接登録できません。親要素に委譲イベントを登録してください:$(document).on("click", ".toggle-btn", function(){...})