Webで遊ぼ!

Web制作を
遊び感覚で。

MENU BOX
Webで
遊ぼ!
OPEN

ホーム

 > 

 > 

CSS:要素の表示⇔非表示の切り替えテクニック

CSS:要素の表示⇔非表示の切り替えテクニック

例えば、『PC表示ではサイドバーを表示させたいけど、スマホ表示ではサイドバーを設置するスペースがないので消したい(非表示にしたい)』…といったように、Webページのパーツを状況に応じて非表示にしたいケースは多いです。

そんな時、まず思いつくのは、displayプロパティを使った方法ではないでしょうか?

確かに、display: none;とするだけで、解説の必要もないぐらい簡単に要素を非表示にすることができます。

ですが表示と非表示をアニメーションにして切り替えたい場合など、display: none;では不都合が起こる場合もあるので、なんでもかんでもdisplayプロパティで解決するというわけにはいきません。

というわけで今回はdisplayプロパティで非表示にする方法はもちろん、違う方法で要素を非表示にする方法をご紹介します。

– 目次 –

単に非表示にしたい時

要素を非表示にしたいケースは大きく分けて2パターンあるかと思います。
1つは、冒頭でも例として出しましたが、デバイスによってサイドバーなどを非表示にしたい場合。
そしてもう1つは、メニューの小項目など、普段は隠しておきたいが必要に応じて表示と非表示をアニメーションで切り替えたい…という場合です。

要素を非表示にするだけで、アニメーションによる表示切り替えが必要ない場合は、displlay: none;で消してしまうのが一番楽です。

displayプロパティを使って非表示にした要素は、単に見えなくなるというだけでなく、要素の幅や高さもなくなり、クリックも不可になってくれます。
そのため、width/heightやpointer-eventプロパティを同時に設定する必要がありません。

非表示にしたい要素をセレクタ指定し、displayプロパティを適用させるだけなので、CSS調整も簡単です。
当然ですが、子孫要素も含めて要素が非表示になります。

下のサンプルは、pタグの親要素であるdivタグにdisplay: none;を適用させるボタンをつけたものです。
ボタンをクリックすると、pタグの文章も含めて全て非表示になることがわかります。

この文章も含めて非表示になります。

コードは以下の通りです。

 	<style>
	.display_none {
	margin: 3rem auto;
	padding: 4%;
	background-color: whitesmoke;
	}
	.dis_none_bt {
	font-size: 16px;
	margin: 2rem auto;
	}
	</style>
	
	<div class="display_none active">
		<p>この文章も含めて非表示になります。</p>
	</div>
	<button class="dis_none_bt">display: none;を適用する</button>
	
	<script>
	{
		const displayNone = document.querySelector('.display_none');
		const dis_none_bt = document.querySelector('.dis_none_bt');
		
		dis_none_bt.addEventListener('click' ,  () => {
		if(displayNone.classList.contains('active')){
			dis_none_bt.textContent ='元に戻す';
			displayNone.style.display = 'none';
			displayNone.classList.remove('active');
		}
		else {
			dis_none_bt.textContent ='display: none;を適用する';
			displayNone.style.display = 'block';
			displayNone.classList.add('active');
		}
		});
		
	}
	</script>

また単に要素が見えなくなるだけでなく、幅と高さがなくなるため、表示・非表示を切り替えると他の要素が移動することがわかります。

ただ、ボタンによる表示切り替えで違和感を持った方もいらっしゃるのではないでしょうか?
ボタンを押した瞬間、パッと非表示⇔表示に切り替わってしまうので、一瞬何が起こったのか分かりづらい感じがします。

displayプロパティはtransitionが無効であるため、transitionプロパティを指定したとしても、ゆっくりと切り替え表示にすることはできません。

なのでdisplayプロパティを使って非表示にする場合は、非表示にしたままで良い場合や、表示・非表示を切り替えるにしてもフワッとした切り替え方(アニメーション・トランジション)にする必要がない場合に向いています。

    POINT!
  1. ・単純に非表示にするだけなら、やはりdisplay: none;と指定するのが楽!
  2. ・displayプロパティで非表示にしたものは幅や高さが無くなり、クリックもできず、存在しないように扱われる!
  3. ・ただし、transitionが無効なので時間をかけて非表示にしたい場合などには向かない方法!

時間をかけて非表示にしたい場合

displayプロパティを使って非表示にする方法では、アニメーションにできず一瞬で非表示になってしまうという問題がありました。
ある程度時間をかけて非表示⇔表示にしたい場合は、他の方法で要素を非表示にする必要があります。

他の方法と言っても色々ありますが、わかりやすいのはwidth/heightと、opacity/visibilityを併用する方法ではないかと思います。

要するに、幅や高さを0にして、かつ不透明度を0%にしたら非表示と同等になるという理屈です。
ちなみに、visibilityを同時に指定するのはリンクなどクリックイベントがあるものを隠したい場合、クリックできないようにしておいた方が良いからです。

また、display: none; は要素を単に見えなくするだけでなく、存在しないように扱う(幅や高さも消える)ので、width/heightを0に指定する必要はありませんが、opacity/visibilityは幅と高さが残るので、width/heightを0にしないと無駄な空白ができてしまいます。

width/height、opacityプロパティはいずれもtransitionプロパティが適用されるので、状態の変化にかける時間を指定することができます。
なので、例えば下のようなアコーディオン式の開閉メニューなどによく使われます。

  • クリックでメニューが開きます
  • メニュー1

今回のサンプルはheightとopacityで表示・非表示を切り替えているので、切り替わりが一瞬ではなく、時間をかけて変化するようになっていることが確認できますね。
※当然、transitionプロパティも指定しています。

上のアコーディオン式の開閉メニューのサンプルコードはこちら▼です。

	<style>
	.sample_menu_outer {
		margin: 4rem auto;
		}
	.sample_menu {
		width: 300px;
		padding: 10px 20px;
		}
	.sample_menu_parent {
		background-color: white;
		cursor: pointer;
		}
	.sample_menu_parent::before {
		content: '▼';
		display: inline-block;
		transform: rotate(-90deg);
		transition: .4s;
		}
	.sample_menu_parent.active::before {
		transform: rotate(0deg);
		}
	.sample_menu_child {
		background-color: darkgrey;
		color: white;
		height: 0;
		opacity: 0;
		visibility: hidden;
		transition: .4s;
		}
	.sample_menu_child.active {
		height: 2rem;
		opacity: 1;
		visibility: visible;
		}
	</style>
	
	<div class="sample_menu_outer">
		<ul>
			<li class="sample_menu sample_menu_parent">クリックでメニューが開きます</li>
			<li class="sample_menu sample_menu_child">メニュー1</li>
		</ul>
	</div>

	<script>
		{
			const sampleMenuP = document.querySelector('.sample_menu_parent');
			const sampleMenuC = document.querySelector('.sample_menu_child');

				sampleMenuP.addEventListener('click', () => {
				sampleMenuC.classList.toggle('active');
  				sampleMenuP.classList.toggle('active');
			});

		}
	</script>

このように、表示⇔非表示を繰り返す必要があり、かつアニメーション(トランジション)の設定が必要な場合は、transitionが有効なopacityやvisibilityプロパティを上手に活用していきましょう。

    POINT!
  1. ・width/heightとopacity/visibilityを組み合わせて非表示にする方法もある!
  2. ・width/height、opacity/visibilityは、いずれもtransitionプロパティが有効!
  3. ・時間をかけて表示⇔非表示にしたい場合は、こちらの方法で切り替えるようにしよう!

補足説明:opacity

前章では、opacity・visibility・heightの3つのプロパティを使って要素を非表示にしましたが、opacityだけだとどうなるのでしょうか?
結論から言うと、透明になるだけでクリックできるし、幅や高さも残るという結果になります。

下にサンプルボタンを用意しました。
クリックすると、「クリックされました」というお知らせメッセージが出てくるようになっています。

さて、ここからが問題です。
サンプルボタンにopacity: 0;を適用させて透明にしてみましょう。
※分かりやすいようにbutton要素をdivタグの子要素とし、div要素に点線の枠を指定してボタンの位置を示しています。

というわけで、透明になって見えなくなっただけで幅や高さが残っているのと、クリックもできてしまうことが確認できますね。
もともとクリックできない(してもアクションが起こらない)要素であれば問題ないですが、リンクなどクリックでアクションが起こる要素はopacityで見えなくするだけでは問題があると言えます。

    POINT!
  1. ・opacityだけでは透明(不透明度が0)になるだけで、幅や高さが残る!
  2. ・さらにクリックイベントも有効のまま!
  3. ・クリックでアクションが起こる要素を隠したい場合、opacityプロパティで見えなくするだけでは不十分!

補足説明:visibility

visibilityプロパティでも要素を非表示にできますが、visibilityを使っても幅と高さは残ります。(opacityと一緒)
ですが、クリックイベントは起こらなくなるという違いがあります。

下は、visibilityプロパティを使って非表示にしたボタンですが、前章のopacityで透明にしたものと違ってクリックしても何も起こらないことが確認できます。

visibility: hidden;を解除すると、当然ですがボタンが現れてクリックできるようになります。

ただ幅と高さが残るので、表示⇔非表示をアニメーションにしたければ、やはりvisibilityだけでは不十分と言えます。
さらに、visibilityはtransition対応ですが不透明度を操れるCSSプロパティではないので、フワッと消えたり現れたりするアニメーションにしたい場合、visibilityだけではできません。

下のテキストは、visibilityのみで表示⇔非表示を指定したものです。(transitionも指定しています)
透明度は変わらないので、アニメーションという感じにならないことがわかりますね。

下のボタンクリックで表示⇔非表示切り替え

もちろん、アニメーションの指定方法や種類によってはopacityプロパティの指定が必要ない場合も考えられますが、透明度変化を伴うアニメーションにしたい場合はopacityプロパティも合わせて指定する必要があります。
そもそもアニメーションが必要ない場合はdisplayプロパティでも良いでしょう。

    POINT!
  1. ・visibilityだけでも幅と高さは残る!
  2. ・opacityと違って、要素のクリックイベントは起こらなくなる!
  3. ・不透明度の変化を伴うアニメーションにしたい場合は、opacityと合わせて指定しよう!
– 関連記事 –

今回の動画で紹介したコード!

今回の解説動画で使用したコードです。学習用としてご自由にコピペしてお使い下さい。(※スクロールできます)

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>無題ドキュメント</title>
</head>

<body>
	<style>
		li {
			list-style: none;
		}
	.sample_menu_outer {
		margin: 4rem auto;
		}
	.sample_menu {
		width: 300px;
		padding: 10px 20px;
		}
	.sample_menu_parent {
		background-color: whitesmoke;
		cursor: pointer;
		}
	.sample_menu_parent::before {
		content: '▼';
		display: inline-block;
		transform: rotate(-90deg);
		transition: .4s;
		}
	.sample_menu_parent.active::before {
		transform: rotate(0deg);
		}
	.sample_menu_child {
		background-color: darkgrey;
		color: white;
		height: 0;
		opacity: 0;
		visibility: hidden;
		transition: .4s;
		}
	.sample_menu_child.active {
		height: 2rem;
		opacity: 1;
		visibility: visible;
		}
	</style>
	
	<div class="sample_menu_outer">
		<ul>
			<li class="sample_menu sample_menu_parent">クリックでメニューが開きます</li>
			<li class="sample_menu sample_menu_child"><a href="#">メニュー1</a></li>
		</ul>
	</div>

	<script>
		{
			const sampleMenuP = document.querySelector('.sample_menu_parent');
			const sampleMenuC = document.querySelector('.sample_menu_child');

				sampleMenuP.addEventListener('click', () => {
				sampleMenuC.classList.toggle('active');
  				sampleMenuP.classList.toggle('active');
			});

		}
	</script>

</body>
</html>

« »

著者について- author profile -

ROYDOプロフィール写真
ROYDO

学校を卒業後、医療福祉業界で専門職に従事。
しかしやりたいこととは違い、どこか違和感を抱えながらも「みんな嫌々でも仕事を頑張ってる!良い年して好きを仕事にしたいとかそんな考えは甘い!」と自分に言い聞かせる日々を送る。
そんな中、せめて趣味として何かできたら…という気持ちで、前から気になっていた地元のIT・Webデザインスクールに問い合わせて体験してみたところ、Web制作・グラフィックデザインといったクリエイティブの面白さにどっぷりハマる。
Webデザインスクール講座を修了後、30代業務未経験という状態からクラウドソーシングでホームページ作成の仕事を受注。

現在もWebサイト・グラフィック制作系の仕事を受注しながらブログで情報発信を続ける。

Twitterアイコン Instagramアイコン