海外のウェブサイトでよくみる「要素が画面内に入ったらふわっとフェードインするあれ」の実装方法

最近よく見るようになりましたエフェクトの実装方法です。海外のおしゃーなウェブサイトは必ずといっていいほど取り入れているように思います。

fadein

デモ作りました。要するにこういうやつです。

以下、これのつくりかたを紹介します。

基本的な考え方

  1. アニメーションはCSS3のtransitionで制御する
  2. アニメーションの開始トリガーをjsで制御する

という感じで、CSS3とjsのあわせ技で頑張ります。

具体的なマークアップ

コーディング方法です。

HTML

<div>

	<section class="fadein">
		<h2>情報設計</h2>
		<p>何かしらの説明文。何かしらの説明文。何かしらの説明文。</p>
	</section>

	<section class="fadein">
		<h2>サイトマップ</h2>
		<p>何かしらの説明文。何かしらの説明文。何かしらの説明文。</p>
	</section>

	<section class="fadein">
		<h2>ワイヤーフレーム</h2>
		<p>何かしらの説明文。何かしらの説明文。何かしらの説明文。</p>
	</section>

</div>

何の取り得も無いhtmlです。エフェクトをかけたい単位に、例えば「fadein」といったclassを加えておきます。

CSS

今回の一番のポイント、CSS3のtransitionを使います。

/* 画面外にいる状態 */
.fadein {
	opacity : 0.1;
	transform : translate(0, 50px);
	transition : all 500ms;
	}

/* 画面内に入った状態 */
.fadein.scrollin {
	opacity : 1;
	transform : translate(0, 0);
	}

前半ではデフォルト = エフェクトがかかる前の状態を指定します。fadeinのclassだけが付与された要素は「透明度が0.1で、下方に50px移動している」状態となっています。本来表示したい位置より50px下で、むっちゃ半透明な状態です。

後半ではエフェクト後の状態 = 読ませたい状態を指定します。”fadein” と “scrollin” というclassがダブルで加わると「透明度が1で、元の位置に移動している」状態になります。

で、5行目にいるtransitionで、この間をアニメーションで繋ぐということをやっています。こうしておくと、「scrollinというclassが付いた瞬間にアニメーションが始まる」状態となります。

要するに、画面内に要素が入ったら

<section class="fadein">
	<h2>情報設計</h2>
		<p>何かしらの説明文。何かしらの説明文。何かしらの説明文。</p>
</section>

↓ 画面内に入ると

<section class="fadein scrollin">
	<h2>情報設計</h2>
		<p>何かしらの説明文。何かしらの説明文。何かしらの説明文。</p>
</section>

こういう変化を起こせばいい、というようにします。そして、この「scrollin」を付与するトリガーを、jsで制御します。

javascript

$(function(){
	$(window).scroll(function (){
		$('.fadein').each(function(){
			var elemPos = $(this).offset().top;
			var scroll = $(window).scrollTop();
			var windowHeight = $(window).height();
			if (scroll > elemPos - windowHeight + 200){
				$(this).addClass('scrollin');
			}
		});
	});
});

※要jQuery。
fadeinというclassを持っている要素が、画面内に入ってさらに200pxスクロールすると、この要素にscrollinというclassを加える、ということをやっています。

7行目の「+200」は削除しても構いません。
削除すると「画面内に入った瞬間にclassが付与=アニメーションが始まる」ことになります。こうしてしまうと、画面の下の方でエフェクトが完了してしまい、気付きにくいかなぁと思って加えています。ここはいろいろ試してみつつ、お好みで決めるとよいでしょう。

ということで、一応以上で「要素が画面内に入ったらふわっとフェードインする」エフェクトはできます。

ほんで、下はちょっとした応用編です。

横に並ぶ要素を左から右でややズラすには

fadein_002

要素が横に並んでいる場合、いっぺんにフェードインしても芸がないので、ちょっとずつ時間差をつけることを考えます。デモの3セクション目はこれの例です。

やり方はいろいろあると思うのですが、今回はCSS3の「transition-delay」を使いました。jsの発火条件には手を加えずに、CSSだけで制御ができてお手軽だからです(というか、個人的にjsはまだ苦手意識があるのであんまりjsをいじりたくないというのが本音です)。

CSS

/* 2つ目の要素に200msのdelayをかける */
#effect2 > div .fadein:nth-of-type(2) {
	-moz-transition-delay:200ms;
	-webkit-transition-delay:200ms;
	-o-transition-delay:200ms;
	-ms-transition-delay:200ms;
	}
/* 3つ目の要素に400msのdelayをかける */
#effect2 > div .fadein:nth-of-type(3) {
	-moz-transition-delay:400ms;
	-webkit-transition-delay:400ms;
	-o-transition-delay:400ms;
	-ms-transition-delay:400ms;
	}

transition-delayは、文字通りtransitionが開始するタイミングを指定するものです。いやー便利ですねCSS。
ちょっと遅延させたい要素を指定して、バカらしいですがひとつづつtransition-delayを設定しています。あんまり数が多くなければこれでも許容範囲かと。
時間差は、200msくらいがちょうどいいと感じました。400msまで間隔をあけるともっさりした印象です。

追記:ページを開いた直後にアニメーションさせる

この記述だとページロード直後に起動しないという弱点があり、どっかで改良しないとなぁと思ってたら、やってくれた方がいらっしゃいました。

要素をふわっと出す、css3アニメーションで簡単エフェクト。 | LittleThings

大変助かります!

この方法の弱点

デメリットを書いておきます。

js無効だとダメ

CSSでデフォルトで透明にしているため、jsが切れていると表示されません。
そのケースにも対応するなら、アニメーションもjsで制御した方がいいと思います。大企業サイトならともかく、個人サイトなどでそこまでカバーする理由は少ないので、後はポリシーの問題かと。今回は、jsが切れているケースを考え始めるとキリがないのと、CSS3でアニメーションした方が今ドキな気がするという理由でこちらを選択しました。

iOSではダメ

2018年現在、iOSでも問題無いように思います。
iOSではこの処理は切った方がいいです。iOSの場合、スクロールが終わったタイミングでスクロール位置を取得するらしいので(スクロールしている「最中」は発火しない)、まともに機能しません。

htmlがちょっとだけ煩雑になる

ただの私の勝手なポリシーで、htmlには「文章の意味と関係しないマークアップはしない」主義なのですが、今回は泣く泣く(文章上)意味を持たないclassをつけました。このエフェクトをつける要素をhtml側で統一して指示できるようにしておかないと、CSSやjsが結構めんどくさいことになるからです。

たぶん確認環境

  • IE10 / 11(10は未確認ですが対応してるはず)
  • Firefox
  • Chrome
  • Safari

transitionが効くことが前提ですので、IE8や9はNGなはずです。