ボタンで要素を出したり隠したりする「表示/非表示の切り替え」は、JavaScriptで頻出の処理です。方法はいくつかありますが、大事なのは「どれを使うか」より「隠したとき場所を残すかどうか」です。
この記事では、各手法の違いと使い分けを整理したうえで、スニペット(必要な部分だけ)の動くコードで解説します。
element.classList.toggle("hidden") か element.hidden = !element.hidden でOK。隠したときに場所も消したいなら display:none、場所を残したいなら visibility:hidden を選びます。style.display の直接操作には判定の落とし穴があるので注意します。まず違いを理解する(場所が残るかどうか)
「非表示」と言っても、レイアウト上の場所が消えるか残るかで結果が変わります。ここを押さえると手法選びで迷いません。
| 方法 | 見え方 | レイアウトの場所 | こんな時に |
|---|---|---|---|
display:none |
完全に消える | 残らない(詰まる) | 通常の表示/非表示 |
visibility:hidden |
見えないだけ | 残る(空白で占有) | 場所をズラしたくない |
hidden属性 / el.hidden |
消える(=display:none相当) | 残らない | 最短・意味的に隠す |
opacity:0 |
透明(操作は可能) | 残る | フェードなどの演出 |
classList.toggle で切り替える(基本・推奨)
もっとも素直な方法です。display:none を持つ .hidden クラスを用意し、classList.toggle() で付いていれば外す・無ければ付けるを1行で行います。
.hidden {
display: none;
}
const btn = document.getElementById("toggle");
const box = document.getElementById("box");
btn.addEventListener("click", () => {
box.classList.toggle("hidden"); // 付け外しを1行で
});
古い記事では if (classList.contains(...)) remove() else add() と書きがちですが、toggle() ならその分岐は不要です。classList の詳しい使い方はclassListの使い方を参照してください。
element.hidden で最短に切り替える
専用クラスすら用意せず、HTML標準の hidden 属性で切り替える方法です。el.hidden = true で display:none 相当になります。
btn.addEventListener("click", () => {
box.hidden = !box.hidden; // true/false を反転するだけ
});
display を指定するCSS(例:#box { display: flex; })があると、そちらが hidden 属性より優先されて隠れないことがあります。その場合は [hidden] { display: none; } をCSSに足すか、前述の .hidden クラス方式を使います。style.display を直接操作する(罠に注意)
インラインstyleの display を直接書き換える方法です。一見シンプルですが、判定に落とし穴があります。
btn.addEventListener("click", () => {
if (box.style.display === "none") {
box.style.display = ""; // 空文字でCSS既定の表示に戻す
} else {
box.style.display = "none";
}
});
box.style.display はインラインstyleしか読みません。表示状態をCSS(スタイルシート)側で指定していると初期値は空文字 "" になり、=== "none" の判定が外れて初回クリックが逆に動くことがあります。また戻すときは "block" 固定にすると元が flex などでも強制的にblockになってしまうため、""(空文字)でCSS既定に戻すのが安全です。確実さを求めるなら classList や hidden を使いましょう。visibility で場所を残して隠す
隠してもレイアウトの場所を保ちたいとき(隣の要素をズラしたくないとき)は visibility を使います。display:none と違い、空白として領域が残ります。
.invisible {
visibility: hidden;
}
box.classList.toggle("invisible");
jQueryなら toggle() 一発
すでにjQueryを使っているプロジェクトなら、toggle() 一行で切り替えられます(新規でこのためだけにjQueryを入れる必要はありません)。
$("#box").toggle();
アニメーション付きの表示切り替えなど、jQueryでの実装はボタンクリックで要素の表示・非表示を切り替える完全ガイドで詳しく解説しています。
アクセシビリティに配慮する(aria-expanded)
開閉ボタンには aria-expanded を付け、状態に合わせて更新すると、スクリーンリーダーにも開閉が正しく伝わります。要素自体は hidden 属性(または display:none)で隠すと、読み上げ対象からも外れます。
btn.addEventListener("click", () => {
const willOpen = box.hidden; // 今が非表示なら開く
box.hidden = !willOpen;
btn.setAttribute("aria-expanded", String(willOpen));
});
opacity:0 や visibility:hidden は見た目は隠れても、opacity:0 の要素はクリックでき読み上げ対象にも残るため、「本当に隠す」目的には display:none / hidden が適しています。フェードで切り替えたいとき
display は基本的にアニメーションできません。ふわっと消すフェードをしたいときは、opacity と visibility をtransition で組み合わせます(透明にしてから場所を消す)。opacity / visibility の挙動は要素を点滅させる方法でも具体的に扱っています。
よくある質問(FAQ)
element.classList.toggle("hidden") でCSSの display:none クラスを付け外しするか、element.hidden = !element.hidden で切り替えます。CSSと分離できる前者がメンテナンスしやすくおすすめです。display:none は要素がレイアウトから消え、場所も詰まります。visibility:hidden は場所を残したまま見えなくなるだけです。隣の要素をズラしたくないときは visibility を使います。display はアニメーションできないため、opacity と visibility を組み合わせます。opacity を transition でフェードさせ、終了後に visibility:hidden にする形が定番です。hidden 属性(または aria-hidden="true")で読み上げ対象から外し、開閉ボタンの aria-expanded を状態に合わせて更新します。これでスクリーンリーダーにも開閉状態が正しく伝わります。まとめ
要素の表示/非表示は、まず「場所を残すかどうか」で考えると手法が決まります。場所も消すなら display:none(classList.toggle か el.hidden で操作)、場所を残すなら visibility:hidden です。
実装は classList.toggle("hidden") か element.hidden が基本。style.display の直接操作は判定の罠があるため、確実さを求めるならクラス方式が無難です。開閉UIでは aria-expanded も忘れずに更新しましょう。

