Webデザインやフロントエンド開発において、要素の表示・非表示を切り替える操作は避けて通れない非常に重要なプロセスです。
ユーザーインターフェースの動的な変化を実現するために、CSSにはいくつかの手法が用意されていますが、中でも頻繁に利用されるのが「display: none」と「visibility: hidden」です。
一見するとどちらも「要素を隠す」という同じ目的を達成するように見えますが、その内部的な挙動やブラウザのレンダリングに与える影響は根本的に異なります。
本記事では、2026年現在の最新のWeb標準仕様を踏まえながら、これら二つのプロパティの細かな違いをプロフェッショナルの視点で詳しく比較していきます。
それぞれの特性を正しく理解することで、レイアウト崩れの防止やアクセシビリティの向上、さらにはパフォーマンスの最適化に役立てることができるでしょう。
display: noneとvisibility: hiddenの根本的な概念
まず、これら二つのプロパティが持つ基本的な定義について整理しておきましょう。
display: noneとは
display: noneを指定すると、対象となる要素はレンダリングツリーから完全に除外されます。
これは単に目に見えなくなるだけでなく、その要素が存在しなかったかのように、確保されていたスペースも消滅することを意味します。
ブラウザは対象要素の幅や高さを計算せず、周囲の要素は詰められる形で再配置されます。
visibility: hiddenとは
一方でvisibility: hiddenは、要素を「不可視の状態」にするだけで、レンダリングツリー上には保持し続けます。
つまり、要素が見えなくなっても、その要素が占有していた領域(透明な空間)はそのまま残ります。
透明人間がそこに立っているような状態をイメージすると分かりやすいかもしれません。
レイアウトへの影響と領域の保持
最も大きな違いは、ページ全体のレイアウトに与える影響です。
この挙動の違いを理解していないと、意図しないレイアウト崩れを引き起こす原因となります。
display: noneによる領域の消滅
display: noneを適用した要素は、ドキュメントのフローから完全に切り離されます。
以下のコード例で、その挙動を確認してみましょう。
/* display: none の例 */
.box-hidden {
display: none; /* 要素も領域も完全に消える */
}
このスタイルが適用されると、後続の要素は空いたスペースを埋めるために上方向や左方向へ移動します。
動的なタブ切り替えや、メニューの展開などで「不要なものを完全に消したい」場合に適しています。
visibility: hiddenによる領域の維持
次に、visibility: hiddenの場合を見てみましょう。
/* visibility: hidden の例 */
.box-invisible {
visibility: hidden; /* 見えないが、領域は確保されたまま */
}
この場合、要素は透明になりますが、元々持っていた「幅」や「高さ」は維持されます。
周囲の要素が移動することはないため、ページのレイアウト構造を崩したくない場面で非常に有効です。
継承(Inheritance)における挙動の違い
初心者が見落としがちなポイントが、子要素への影響、すなわち「継承」の仕組みです。
display: noneは子要素も含めて完全に消える
親要素にdisplay: noneを指定した場合、その子要素に対してdisplay: blockなどを指定しても、子要素を表示させることはできません。
親要素がレンダリングツリーから除外されている以上、その中身も一括で処理対象外となるためです。
visibility: hiddenは子要素で上書きができる
驚くべきことに、visibility: hiddenは継承されますが、子要素側で上書きが可能です。
親要素がvisibility: hiddenであっても、子要素にvisibility: visibleを指定すれば、その子要素だけを表示させることができます。
以下のコードはこの特殊な挙動を示しています。
<!-- HTML構造 -->
<div class="parent">
親要素は見えません
<div class="child">子要素だけが見えます</div>
</div>
/* CSS設定 */
.parent {
visibility: hidden; /* 親は隠す */
}
.child {
visibility: visible; /* 子だけを強制的に表示する */
}
このテクニックは、特定のコンテキストでのみ要素を部分的に表示したい場合に役立ちます。
アクセシビリティとSEOへの影響
モダンなWeb開発においては、目に見える部分だけでなく、スクリーンリーダーなどの支援技術への対応も欠かせません。
スクリーンリーダーによる読み上げ
display: noneとvisibility: hiddenは、どちらもスクリーンリーダーによって読み上げられません。
支援技術からも完全に隠したい情報であれば、どちらを使用しても問題はありません。
しかし、アクセシビリティの観点では、フォーカス制御にも注意が必要です。
visibility: hiddenで隠された要素の中にリンクやボタンが含まれている場合、それらはキーボード操作のフォーカス対象からも外れます。
SEOへの配慮
Googleなどの検索エンジンは、ユーザーに隠されたコンテンツ(隠しテキスト)を嫌う傾向があります。
ただし、UI上の理由で適切にdisplay: noneを使用することは、スパム判定の対象にはなりません。
重要なコンテンツをSEO目的で不当に隠すのではなく、ユーザー体験を向上させるための手段として正しく使い分けることが求められます。
レンダリングパフォーマンスの差異
ブラウザが画面を描画する際の内部プロセスにも違いがあります。
リフロー(Reflow)とリペイント(Repaint)
display: noneを切り替えると、レイアウトの再計算が必要になるため、「リフロー(Reflow)」が発生します。
リフローは計算コストが高く、ページ全体の要素が多い場合にはパフォーマンスに影響を与える可能性があります。
対して、visibility: hiddenの切り替えは、レイアウトに変化を与えないため「リペイント(Repaint)」のみで済む場合が多いです。
頻繁に表示状態を切り替えるアニメーションなどでは、パフォーマンス面でvisibilityが有利になるケースもあります。
CSS Transitions(アニメーション)との相性
2026年現在のモダンブラウザでは、アニメーションの扱い方も進化しています。
visibilityはアニメーションが可能
visibilityプロパティは、CSS Transitionsでアニメーションさせることができます。
厳密には数値的な中間値はありませんが、visibleからhiddenへ切り替える際に遅延を設定することが可能です。
これにより、ふわっと消えるフェードアウト効果の終了時に、要素を非表示(かつ操作不能)にする処理が容易になります。
displayのアニメーション(最新仕様)
従来、displayプロパティはアニメーションが不可能とされてきました。
しかし、最新のCSS仕様(allow-discreteなど)により、displayプロパティの切り替えを伴うエントリー・イグジットアニメーションが可能になりつつあります。
/* 2026年スタイルのモダンな書き方例 */
.fade-element {
transition: display 0.5s allow-discrete, opacity 0.5s;
opacity: 1;
}
.fade-element.is-hidden {
display: none;
opacity: 0;
}
@starting-style {
.fade-element {
opacity: 0;
}
}
このように、@starting-styleを活用することで、display: noneの状態からでも滑らかなアニメーションを実現できるようになっています。
比較表:display: none vs visibility: hidden
これまでの解説を一覧表にまとめました。
| 特徴 | display: none | visibility: hidden |
|---|---|---|
| 物理的なスペース | 消滅する | 確保されたまま残る |
| ドキュメントフロー | 完全に除外される | 維持される |
| 子要素での再表示 | 不可能 | 可能(visibleで上書き) |
| ブラウザの負荷 | リフロー(高負荷) | リペイント(低負荷) |
| 主な用途 | タブ、モーダル、不要な要素 | プレースホルダー、位置維持 |
具体的な使い分けのケーススタディ
実際の開発現場で、どちらを選ぶべきか迷った際の指針を示します。
display: none を選ぶべき場面
- ハンバーガーメニューの開閉など、非表示時に他の要素を詰めたい場合。
- フォームの入力内容に応じて、特定の項目を完全に出し分けたい場合。
- 条件分岐によって全く異なるコンテンツを同じ場所に配置したい場合。
visibility: hidden を選ぶべき場面
- 画像の読み込み待ちなどで、レイアウトがガタつく(CLS: Cumulative Layout Shift)のを防ぎたい場合。
- JavaScriptで位置計算を行う際に、要素の座標を取得し続けたい場合。
- マウスオーバー時にのみ表示されるヒントテキスト(ツールチップ)の領域をあらかじめ確保しておきたい場合。
JavaScriptとの連携における注意点
プログラムからこれらの要素を操作する場合、DOM上にはどちらも存在しているという点に注意してください。
document.querySelectorで要素を取得することはどちらも可能です。
しかし、display: noneの要素はoffsetWidthやoffsetHeightが「0」になります。
一方で、visibility: hiddenの要素は、非表示であっても本来のサイズを取得することができます。
動的にサイズ計算を行うライブラリを使用している場合、この差がバグの原因になることがあります。
まとめ
CSSのdisplay: noneとvisibility: hiddenは、どちらも要素を隠すためのプロパティですが、その本質は「存在の抹消」か「透明化」かという大きな違いがあります。
レイアウトを詰めて完全に消去したいならdisplay: noneを選択し、領域を維持して見た目だけ消したいならvisibility: hiddenを活用しましょう。
また、子要素の継承ルールや、リフロー・リペイントといったパフォーマンス面の違い、さらに最新のCSSによるアニメーション手法まで考慮できるようになると、より高度なフロントエンド開発が可能になります。
それぞれの特性を適材適所で使い分け、ユーザーにとっても開発者にとっても最適なWebサイトを構築していきましょう。
