visibility の切り替えとは何か
visibility は「要素を見える/見えない」にするプロパティです。visibility: hidden にすると見えなくなりますが、レイアウト上の“場所”は残ります(スペースを確保したまま非表示)。再表示は visibility: visible に戻します。ここが重要です:display: none と違い、レイアウトは維持されるため、配置を崩さずに一時的に隠す場面に向いています。
display: none と visibility: hidden の違い(選び方の軸)
目的別の使い分け
- レイアウトごと消したい: display: none(スペースも消える)
- 場所は保ったまま隠したい: visibility: hidden(スペースは残る)
- アニメーションさせたい: visibility は transition 可能(opacity と相性が良い)
ここが重要です:表示を消すだけならどちらでも隠せますが、“スペースを残すか”が最大の違い。UI の意図に合わせて選びましょう。
基本の切り替え(クラス方式が保守に強い)
クラスで一元管理(推奨)
<style>
.is-hidden { visibility: hidden; }
.is-visible { visibility: visible; }
</style>
<button id="toggle">切り替え</button>
<div id="panel" class="panel is-visible">内容</div>
<script>
const btn = document.getElementById("toggle");
const panel = document.getElementById("panel");
btn.addEventListener("click", () => {
const nowHidden = panel.classList.toggle("is-hidden");
panel.classList.toggle("is-visible", !nowHidden);
btn.textContent = nowHidden ? "見せる" : "隠す";
});
</script>
HTMLここが重要です:見え方のルールは CSS に集約し、JS は“状態クラス”だけ触る。プロジェクトが大きくなっても整合性を保てます。
インラインで最短切り替え(小規模向け)
<div id="panel" style="visibility: visible;">内容</div>
<script>
const panel = document.getElementById("panel");
panel.style.visibility = "hidden"; // 非表示(スペースは残る)
panel.style.visibility = "visible"; // 再表示
</script>
HTMLここが重要です:素早い試作には便利ですが、設計が散らばりやすい。基本はクラス方式に寄せましょう。
深掘り:visibility の実務的な特性
スペースは残る(レイアウトは維持)
ボタンやラベルを一瞬隠したいが、横並びレイアウトを崩したくない場面で有効です。ここが重要です:要素の“幅・高さ・位置”はそのまま。周囲要素の並びが変わりません。
子孫も隠れる(ただし上書き可能)
親を visibility: hidden にすると、原則として子孫も見えなくなります。特定の子だけ見せたいなら、その子に visibility: visible を指定すれば上書きできます。ここが重要です:親子で意図的に“見える/見えない”を分ける設計が可能です。
クリックは防げない(pointer-events を併用)
visibility: hidden は“見えないだけ”。位置は残り、クリック判定が通ることがあります。ここが重要です:操作不可にしたいなら pointer-events: none を併用します。
.hidden {
visibility: hidden;
pointer-events: none; /* クリック/ホバーを受けない */
}
CSSスクリーンリーダー対策(aria-hidden)
見えない要素を読み上げさせたくないなら、aria-hidden=”true” を付けます。ここが重要です:視覚・操作・読み上げの整合性をそろえると UX が安定します。
el.classList.add("hidden");
el.setAttribute("aria-hidden", "true");
JavaScriptアニメーションに強い設計(visibility + opacity)
フェードの基本パターン
<style>
.fade { opacity: 0; visibility: hidden; transition: opacity 180ms; }
.fade.is-show { opacity: 1; visibility: visible; }
</style>
<div id="toast" class="fade">保存しました</div>
<script>
const toast = document.getElementById("toast");
function showToast() {
toast.classList.add("is-show");
setTimeout(() => toast.classList.remove("is-show"), 1500);
}
</script>
HTMLここが重要です:opacity をトランジションさせ、visibility で“見えない状態”を明示。pointer-events: none を足すと操作も防げます。
レイアウト維持が前提の演出
visibility はスペースを保つため、ガタつきがありません。ここが重要です:メニューやツールチップの“スッと出る/消える”演出に向いています。
実践例(ラベルの一時隠し、ツールチップ、ローディング)
ラベルを条件で見せる/隠す(配置維持)
<style>
.label { margin-left: 8px; }
.label.is-hidden { visibility: hidden; }
</style>
<button id="run">実行</button><span id="label" class="label">完了</span>
<script>
const label = document.getElementById("label");
label.classList.add("is-hidden"); // 初期は非表示(スペースは保持)
document.getElementById("run").addEventListener("click", () => {
label.classList.remove("is-hidden"); // 結果に応じて表示
setTimeout(() => label.classList.add("is-hidden"), 2000);
});
</script>
HTMLここが重要です:ボタンの横幅が変わらず、UI が安定して見えます。
ツールチップの表示(フェード + 操作不可)
<style>
.tip { position: absolute; opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 120ms; }
.tip.is-show { opacity: 1; visibility: visible; pointer-events: auto; }
</style>
<div class="field">
<input id="name">
<div id="tip" class="tip">名前を入力してください</div>
</div>
<script>
const tip = document.getElementById("tip");
const name = document.getElementById("name");
name.addEventListener("focus", () => tip.classList.add("is-show"));
name.addEventListener("blur", () => tip.classList.remove("is-show"));
</script>
HTMLここが重要です:opacity/visibility/pointer-events をセットで管理すると、直感的で安全な UI になります。
ローディング覆い(場所は確保、操作を封じる)
<style>
.overlay { position: relative; }
.overlay::after {
content: ""; position: absolute; inset: 0;
background: rgba(255,255,255,.6); visibility: hidden; pointer-events: none;
}
.overlay.is-busy::after { visibility: visible; pointer-events: auto; }
</style>
<div id="card" class="overlay">内容</div>
<script>
const card = document.getElementById("card");
function busy(on) { card.classList.toggle("is-busy", on); }
busy(true); setTimeout(() => busy(false), 1000);
</script>
HTMLここが重要です:覆いは“スペースを保ちつつ操作不可”にできるため、ちらつきなく処理中を伝えられます。
落とし穴と回避策(スペース、クリック、読み上げ)
スペースが残ることを忘れない
visibility: hidden は“空白が残る”ため、詰めたいレイアウトには不向きです。ここが重要です:詰めたいなら display: none、崩したくないなら visibility: hidden。
操作不能にしたいなら pointer-events を併用
見えないのにクリックできると事故につながります。ここが重要です:hidden 時は pointer-events: none をセットで。
アクセシビリティを揃える
読み上げ対象から外すなら aria-hidden を連動。フォーカスも適切に移動/解除します。ここが重要です:視覚・操作・読み上げの一貫性が UX の鍵です。
まとめ
visibility の切り替えは「見えないけれど場所は残す」非表示手段です。レイアウトを崩さずに隠したい場面で選び、操作不可にしたいときは pointer-events、読み上げ制御は aria-hidden を併用。アニメーションは opacity と組み合わせると滑らかで扱いやすい。display: none と目的を区別し、クラス方式で一元管理すれば、初心者でも意図通りで壊れにくい表示制御が書けます。
