CSS

opacityとvisibilityとtransitionでフェードイン・フェードアウト【CSS・Javascript】

CSSでフェードイン・フェードアウトの概要

注意 ※バージョンや環境によっては正常に動作しない可能性があります。

レイアウトは残って良いけど、表示非表示される要素はクリックできないようにしたい、なんて時に使えるフェードイン・フェードアウトです。

クリックを起点に、Javascriptで表示用のクラスを入れ替えます。

cssで表示非表示、透明度、アニメーションの時間を設定しています。

cssでアニメーションの設定をしている時に作った一つの形なのですが、自分の要件を満たさなかったため、ボツにした方法です。

レイアウトが残っても良い場合や、クリックで出し入れする要素が1つしかない場合、などはささっと実装できるので使い道はあるかな~とは思いますが、他の方法のほうが楽かな、とも思ったりします。

  1. レイアウトが残っているフェードインとフェードアウト
  2. 該当の場所をクリックすると、該当の要素が表示と非表示を繰り返す
  3. javascriptはクラスの切り替えに使用する
  4. cssは表示非表示、透明度、アニメーションの時間を設定している
  5. 動作確認はchromeとEdgeだけ。

フェードイン・フェードアウトの動作サンプル

↓の色がついているところをクリックすると動作します。

このラベルをクリック(trigger)
triggerをクリックすると表示される(hide ⇒ show)
triggerをクリックすると消える(show ⇒ hide)

ソースコード

<div class="trigger">
  ここをクリック(trigger)
</div>
<div class="contents hide">
  <div>
    triggerをクリックすると表示される(hide ⇒ show)
    triggerをクリックすると消える(show ⇒ hide)
  </div>
</div>
<style>
.contents {
  background-color: #fff;
  border: 1px solid rgba(0, 0, 0, 0.125);
  border-radius: 0.25rem;
  padding: .5rem;
  margin-top: .5rem;
  }
.hide{
  opacity: 0;
  visibility: hidden;
  transition: 1s;
  }
.show{
  transition: 1s;
  opacity: 1;
  visibility: visible;
  }
.trigger{
  background-color: #bdd4ff;
  }
</style>
<script>
  const trigger = document.querySelector('.trigger');
  const target = document.querySelector('.hide');
  trigger.addEventListener('click', () => {
    target.classList.toggle('hide');  
    target.classList.toggle('show');
  }, false);
</script>
  • tiggerをクリックするとjavascriptでクラスhideとshowを切替
  • hideは非表示・showは表示としてcssで設定
  • 表示と非表示はopacityの透明度とvisibilityで設定
  • 切り替わる時間はtransitionで1秒に設定

html

<div class="trigger">
  ここをクリック(trigger)
</div>
<div class="contents hide">
  <div>
    triggerをクリックすると表示される(hide ⇒ show)
    triggerをクリックすると消える(show ⇒ hide)
  </div>
</div>

クラスtriggerの要素がクリックする場所です。

クラスcontentsの場所が表示されたり非表示になったりする要素です。

contentsにくっついているhideが初期状態を設定しているクラスです。

triggerをクリックするとjavascriptが動作し、hideクラスがshowクラスに変わります。

showクラスがcontentsについている場合にtriggerをクリックすると、showクラスがhideクラスに変わります。

css

<style>
.contents {
  background-color: #fff;
  border: 1px solid rgba(0, 0, 0, 0.125);
  border-radius: 0.25rem;
  padding: .5rem;
  margin-top: .5rem;
  }
.hide{
  opacity: 0;
  visibility: hidden;
  transition: 1s;
  }
.show{
  transition: 1s;
  opacity: 1;
  visibility: visible;
  }
.trigger{
  background-color: #bdd4ff;
  }
</style>
  • contentsは要素のデザインを設定
  • hideは初期状態の非表示。透明度0の非表示
  • showは表示状態。透明度1。showの状態に変わるまでに1秒間。
  • triggerはデザインだけ設定
  • JavaScriptでクリックイベントをトリガーに、hideからshowに変える。
  • visibilityはレイアウトが残る非表示が可能。リンクやマウスオーバーを無効にできる。
  • opacityは透明度の設定。opacityだけだと、リンクやマウスオーバーは有効のままになる。
opacity 0 はリンクやマウスオーバーのイベントは残る
visibility hiddenはレイアウトが残る

contentsは表示・非表示の対象になる要素の見た目を設定しています。

triggerクラスはクリック対象の要素の見た目を設定しています。

hideとshowは非表示と表示を設定したクラスです。hideは非表示・showは表示の状態です。opacityは透明度を設定してます。visibilityはレイアウトを維持したまま要素の表示・非表示を設定をしています。transitionは要素の状態間の変化を設定しています。

javascriptを使用して、クラスがhideからshowに変わると、showに設定してある設定が読み込まれます。2要素間の変化としては、opacityが0から1に変化し、visibilityがhiddenからvisibleに変化します。showに設定しているtransitionにて、変化の時間を1秒と設定しています。

showからhideに変わるとまた非表示に戻ります。

visibilityを設定している理由は、opacityだけだとリンクやマウスオーバーが有効のまま残ってしまうからです。visibilityをhiddenにすることで、リンクもきかなくなります。

レイアウトを残したくない場合は、display:noneを使うか、非表示にしたい要素のheightを0にしてしまう方法があります。

注意点として、display:noneに向かうアニメーションはtransitionとanimationではできません(この記事を書いている時点では、ですが)。

display:noneが読み込まれた瞬間にアニメーションが停止してしまうので、jQueryを使うか、heightを0にするなどの方法があります。

jqueryが簡単です。fadeToggleを使うだけで実装出来ます。

height要素を0にする方法は、heightだけでなく、余白やはみ出る要素へのoverflowなど、気にしないといけない要素が多いです。表示される要素にpaddingを設定していると、そこにもアニメーションが適用されるので、文字が斜めに動くような感じでフェードインするような動作になります。

javascript

<script>
  const trigger = document.querySelector('.trigger');
  const target = document.querySelector('.hide');
  trigger.addEventListener('click', () => {
    target.classList.toggle('hide');  
    target.classList.toggle('show');
  }, false);
</script>
  • クラス指定したtrigerとtargetのドキュメントを変数に保存
  • trigerがクリックされるイベントでクラス変更の動作が行われる
  • クリック時にhideクラスがあれば消去、無ければ追加
  • クリック時にshowクラスがあれば消去、無ければ追加

jqueryのほうが記述は少なくなりそうですが、勉強もかねてjavascriptで記述しています。

変数triggerとtargetを定義して、Document.querySelector()で指定したクラスのドキュメントを取得しています。documentはhtml要素の全てを読み込みます。その中から指定した要素のドキュメントを取得するのがquerySelectorです。querySelectorで('.trigger')と指定すると、html内の最初のtriggerクラスの要素を取得します。二つ目のtriggerがあっても取得されないようです。あくまでも最初のtriggerが取得されます。

addEventListener()では、指定した要素に対して(ここでは変数trigger)起こした特定の動作に対しての処理を記述しています。ここではイベントにclickを指定しているため、クラスtrigger要素がクリックされると、addEventListener()内に指定した関数が呼び出される形です。clickはmouseoverなど他のイベントでも使えます。

triggerがクリックされると、classList.toggleが実行されます。target.classListは、target変数に取り込んだelemnetの中のクラス属性を返しますが、その後につけるのが実際の動作で、ここではtoggleをつけています。toggleは、指定したクラスが含まれていれば削除し、無ければ追加するという動作をします。toggle以外にも、addやremoveなどがあります。

今回の動作では、クラスのhideとshowを入れ替えることで表示を制御します。なので、showとhideが共存することはありません。そのため、toggleの動作で要件を満たします

初期状態はhideが含まれている状態で、triggerがクリックされると、target.classList.toggle('hide')にてhideが消え、target.classList.toggle('show')でshowが追加されます。

トリガーになるクラスを取得して、そのクラスがクリックされたときに、クラスを入れ替えるという、非常に単純な動作になります。

まとめ

今回は要素のレイアウトが残っているフェードイン・フェードアウトなため、javascriptではクラスの入れ替えをしているだけで、アニメーションの設定はcssを使用しています。

レイアウトが残っていい場合は使いやすいですし、デザインレイアウト上必ず余白になる場所にposition absoluteなどで指定して使う、とかも考えられるかな、と思います。

Javascriptも簡単ですし、jqueryだともっと簡単に書けるでしょうし、複雑なスクリプトを書きたくない人にとっても使い勝手があるかなと思います。

javascriptをどうしても使いたくない、という時もあるかと思いますが、その際はinputタグとラベルを使ってトリガーとは別の要素にアニメーションを適用させることができます。以前、クリックしたら矢印を回転させる、というものを作ろうと思いまして、いろいろ調べたことがあったのですが、その時に見つけたのが、inputタグとラベルを使う方法でした。が、Javascriptでええやん、となりました。

とりあえず最初に考えたもので、自分の環境では動いているので、その備忘録としての記事になります。

タイトルとURLをコピーしました