【完全比較】CSSのdisplay:noneとvisibility:hiddenの違いとは?使い分け・注意点まで徹底解説
CSS で要素を「見えなくする」方法はいくつかありますが、代表的なのが display: none
と visibility: hidden
です。同じ「非表示」でも挙動は大きく異なり、使い分けを誤るとレイアウト崩れやアクセシビリティ低下の原因になります。ここでは両者の動きを比較しながら、具体的な活用シーンと注意点を分かりやすく解説します。
基本定義
- display: none … 要素をDOM ツリーから取り除き、レンダリング・フローに参加させません。ブラウザーはその要素を存在しないものとして扱います。
- visibility: hidden … 要素は描画されませんが、占有していたスペースは保持されます。テーブルの行や列を個別に隠す用途にも使えます。
比較早見表
観点 | display:none | visibility:hidden |
---|---|---|
レイアウトへの影響 | 要素を除去。周囲が詰めて再配置 | スペースを保持。レイアウトは変化しない |
スクリーンリーダー | 読み上げ対象外 | 多くの環境で読み上げ対象外* |
フォーカス/クリック | 不可(要素が存在しない) | 不可(要素は見えないが空間は残る) |
再フローコスト | 高い(再計算発生) | 低い(位置は維持) |
代表的な用途 | モーダル開閉、タブ切替 | 一時的な点滅・行列の非表示 |
* 一部の支援技術では読み上げるケースがありますが、原則として「隠れている=無視される」と考えてください。
レイアウトと再フロー
display:none
はフローから要素を外すため、隣接要素が詰め寄りレイアウトが再計算されます。大量の要素を頻繁に切り替える場合、パフォーマンスに影響が出ることもあるので注意が必要です。一方 visibility:hidden
は位置・サイズを保持するため再フローが発生せず、パフォーマンス面で有利です。
アクセシビリティの違い
どちらも視覚的には非表示ですが、display:none
はスクリーンリーダーに完全に無視されるのに対し、visibility:hidden
も多くの場合読み上げ対象外になります(実装による差はあり)。もし視覚的に隠しつつ読み上げさせたい場合は opacity:0
や position:absolute; left:-9999px;
と ARIA 属性を併用するなど、別の手法を検討しましょう。
たとえば、aria-hidden="false"
を明示的に指定することで、支援技術に「読み上げ対象である」ことを伝えることができます。逆に、見た目だけでなく読み上げも避けたい場合は aria-hidden="true"
を指定することで制御可能です。
インタラクション(クリック・フォーカス)
どちらのプロパティも要素を操作不能にします。visibility:hidden
は DOM 上に存在していてもポインターイベントを受け取りません。キーボードフォーカスも同様に移動しないため、フォーム要素を一時的に隠す場合はフォーカス制御にも留意してください。
なお、視覚的には表示されていてもマウスイベントを受け取らせたくない場合は、pointer-events: none
を併用するという手段もあります。これは visibility
や display
とは異なり、ポインター動作のみを無効化できます。
アニメーション・トランジション
CSS トランジションでフェードイン/アウトを行う場合、opacity
を使うのが一般的です。display
と visibility
はトランジションの対象プロパティではないため、滑らかなアニメーションを付けられません。opacity:0 → 1
で視覚的に隠しつつ、アニメーション完了後に display:none
を付与するといったハイブリッド手法がよく採用されます。
使い分けの指針
- 要素を完全に取り除きたい …
display:none
(例:メニューの開閉、不要な DOM の削除) - レイアウトを崩さず一時的に不可視にしたい …
visibility:hidden
(例:テーブル行のフィルタリング、タイマーで文字を点滅) - 視覚的に隠してアニメーションしたい …
opacity
+ 必要に応じてdisplay:none
を併用
▼表示・非表示を切り替える基本的な実装例
<style>
.modal {
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
}
.modal.active {
opacity: 1;
pointer-events: auto;
}
</style>
<div class="modal" id="myModal">モーダルの内容</div>
<button onclick="toggleModal()">表示/非表示</button>
<script>
function toggleModal() {
const modal = document.getElementById('myModal');
modal.classList.toggle('active');
}
</script>
よくある誤解
- 「visibility:hidden ならスクリーンリーダーに読まれる」 → 実際には多くの環境で読み上げられません。読み上げさせたい場合は別の手段を使いましょう。
- 「display:none はパフォーマンスが悪い」 → 再フローが発生するため大量要素の頻繁な切替では確かに負荷が高まりますが、通常規模の DOM であれば問題になるケースは多くありません。
- 「visibility:hidden はクリックできる」 → 要素は存在しますがポインターイベントは無効化されるためクリック不可です。
まとめ
display:none
と visibility:hidden
は「見えなくする」点では同じでも、レイアウト・アクセシビリティ・パフォーマンスにおける影響が異なります。
- レイアウトごと消すなら display:none
- スペースを保ちたいなら visibility:hidden
- 支援技術との両立やアニメーションには opacity など別手段 を検討
用途に応じて適切に選択し、ユーザー体験とメンテナンス性を両立させましょう。