CSSやHTMLでどのように要素を非表示にできるのか
こんにちは、Saku です。
本記事では 「HTML/CSS で要素を非表示にするテクニック」 を、レイアウト・アクセシビリティ・パフォーマンス・SEO の 4 つの軸でまとめていきます。
「display: none;以外に要素を非表示にする方法あるの...?」
そんな疑問がある方は、ぜひ最後までお付いいただければと思います。
1. はじめに
要素の表示/非表示の手法は多々ありますが、基本的に以下の 3 つの観点で選択できると思います。それぞれの細かい説明は、後ほど別の章で説明します。
視覚的なレイアウト
1 つ目は、要素を 「本当に消す」 のか、「場所は残す」 のかです。
端的に言えば DOM から削除するのか、視覚的にだけ非表示(隠す)にするのかと言うことです。前者と後者の違いは、視覚的にみただけではそこまで大差ないかもしれませんが、インタラクションやレイアウトなどの点で異なってきます。
ユーザー操作/支援技術
2 つ目は、「クリック・フォーカス可否」「スクリーンリーダー読み上げの有無」です。
1 つ目に関連している部分もありますが、視覚的には同じでも、インタラクションやアクセシビリティの点で異なってきます。また、視覚的には表示されていてもスクリーンリーダーには読まれないようにすると言った意味での意味での非表示も存在します。
実装コストと保守性
3 つ目は、「JavaScript で表示・非表示を切り替えるのが容易か」「CSS でアニメーションを付与できるか」です。
表示/非表示の方法によって、アニメーションを付与の可否などが異なります。その時望む仕様に応じて、使い分ける必要があります。
上記以外にも 「少ないコード量の変更で済むかどうか」「既存ライブラリと衝突しないか」 も考慮した方がいいと思います。
2. 要素を非表示にする方法一覧
視覚表示 | レイアウト領域 | クリック/フォーカス | A11y ツリー | アニメ可否 | 主な用途 |
---|---|---|---|---|---|
display: none |
なし | × | 除外 | × | ルーティング・条件分岐 |
visibility: hidden |
あり | × | 除外 | × | レイアウト維持の一時非表示 |
aria-hidden="true" |
あり | ○ | 除外 | — | 装飾アイコン・重複テキスト |
opacity: 0 |
あり | ○ | 残る | ○ | フェード演出・モーダル |
Visually Hidden (clip-path 等) |
ほぼなし | ○ | 残る | — | SR 専用テキスト |
アクセシビリティツリー(A11y ツリー)とは?
ブラウザーが DOM/CSSOM を解析した後、スクリーンリーダーなどの支援技術に渡す 意味論的ツリー。display: none
とvisibility: hidden
はツリーからも消えますが、opacity
や Visually Hidden パターンではノードが残るため読み上げ対象になります。Chrome DevTools「Accessibility」パネルで可視化可能です。
DOM ツリーとは?
DOM (Document Object Model) は HTML をノードツリー化したもの。要素がdisplay: none
でも DOM には存在し、JS で取得・変更可能です。element.remove()
すると DOM・A11y ツリー双方から完全に除去されます。
レンダリングやツリーに関して詳しく知りたい方はこちらを参考にしてください。
3. 各方法の使い方と挙動
display: none
3‑1. - 領域(テキスト非表示時に背景色の領域もなくなっていることに注目!!)がゼロになるため リフロー が走る。大量要素を切り替えるとパフォーマンス劣化に注意。
- ノードは DOM 上に残るので JavaScript と親和性良好。
-
transition でフェード不可。代わりに
@keyframes
+animation
で opacity/scale を組み合わせる手も。
visibility: hidden
3‑2. - レイアウト保持 → 表示切替え時にチラつきが少ない。
- 子要素は
visibility: visible
で上書き可能。ツールチップの制御によく使われる。 - 非表示時も タブインデックスはスキップ されるため誤フォーカスは起きない。
aria-hidden="true"
3‑3. - 視覚デザインそのまま。支援技術からだけ隠す ので誤読防止に有効。
- ただしフォーカス取得要素(リンク・ボタン等)に付与すると キーボード操作と読み上げの同期が崩れる ので注意。
opacity: 0
3‑4. - GPU 合成レイヤー が効くためアニメが滑らか。
- 視覚的に透明でも要素がそこにあるため、重なり順で 背面要素がクリックできない ケースがある ⇒
pointer-events: none
で解決。 - A11y ツリーに残るので、aria-live と併用して補足テキストをフェード表示すると SR にも届く。
3‑5. Visually Hidden パターン
- WCAG 2.2 の「SR だけに情報を提示する」推奨実装。
- Safari < 7 と古い IE では
clip-path
非対応のため、古い案件はclip: rect(0 0 0 0);
を併用。 - 文字サイズが 200% でも 1 px 外にはみ出さず、ギャップチェックツールに合格。
4. ブラウザ対応状況(2025‑05 更新)
機能 / プロパティ | Chrome / Edge | Safari | Firefox | Node.js (SSR) | 備考 |
---|---|---|---|---|---|
display / visibility
|
◎ | ◎ | ◎ | — | 全ブラウザで安定。 |
opacity |
◎ (4+) | ◎ (3.1+) | ◎ (2+) | — | IE 9+。GPU 合成は 36+。 |
pointer-events:none |
◎ | ◎ (4+) | ◎ (3.6+) | — | IE 非対応。ポリフィルは限定的。 |
HTML hidden 属性 |
◎ (6+) | ◎ (5.1+) | ◎ (4+) | — | SSR では初期描画時に hidden が効くことを確認。 |
aria-hidden |
◎ | ◎ | ◎ | — | スクリーンリーダー実装差は小さくなったが、旧 NVDA + IE は要検証。 |
clip-path: inset() |
◐ (117+ full) | ◐ (17+ 部分) | ◎ (54+) | — | Safari 17 以前は矩形のみ。 |
content-visibility: hidden |
◎ (85+) | ◎ (18+) | ◎ (125+) | △ (Experimental) | Firefox は 124 以前 flag。SSR では無意味。 |
対応表の読み方
◎: フルサポート ◐: 一部制限 △: 実験的 —: 該当なし
5. パフォーマンス & SEO 視点での注意点
5‑1. レンダリングコスト
-
display:none
は recalc‑style → layout が走るため、大規模リストのトグルはコスト大。virtual scroll 導入を検討。 -
opacity
はペイントのみ変更で済むが、連続アニメで paint storm になると GPU 転送が詰まる。
5‑2. 検索エンジンの扱い
- Googlebot は DOM を実行後にレンダリング評価する。
display:none
で長期的に隠すコンテンツは Hidden Text と判定されるリスク。 -
FAQ やタブ UI での一時的隠蔽はガイドライン違反にならない。アクセシビリティ上も
aria-expanded
を付与して状態を明示すると良い。
6. まとめ
今回は、要素を非表示にする方法について、説明しました。
本記事の内容を端的にまとめると以下になります。
- 目的を言語化: 「レイアウトを崩したい/崩したくない」「SR に読ませたい/隠したい」。
- プロパティ選択: 早見表で最適解を確認。
- ブラウザ互換性: Can I use で最新版をチェックし、フォールバックが必要なら準備。
- アクセシビリティ検証: DevTools > Accessibility でツリー確認 & SR 実機テスト。
- パフォーマンス計測: Performance パネルでレイアウト・ペイントコストを計測。
本稿が、非表示テクニック選定の参考になれば幸いです。
Discussion