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が積み重なり、表示状態がずれていきます。
ボタンを素早く何度もクリックすると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
CSS
transition はGPUで処理されjQueryアニメーションよりパフォーマンスが高いです。特にモバイル端末や大量の要素がある場合に有利です。ただし display:none ↔ block はトランジションが効かないため、max-height や opacity でフェードを実現します。クラス操作の詳細は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形式のアコーディオン・ネスト・アイコン連動・アクセシビリティ完全対応が必要な場合は、アコーディオン実装完全ガイドを参照してください。
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が効かなくなるためです。反対に表示するときは
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(){...})。