【初心者向け】CSSアニメーションとJavaScriptで実装する Webエフェクトの作り方(点滅・桜)

Webサイトにちょっとした「動き」を加えて、ユーザーの目を引いたり、季節感を演出したりしたいと考えたことはありませんか? CSSのアニメーションとJavaScriptを組み合わせることで、比較的簡単に魅力的なエフェクトを実装できます。

この記事では、コピペでも使いやすい2種類のエフェクト(ランダムな点滅エフェクト桜が舞うエフェクト)の実装例を、HTML、CSS (SCSS)、JavaScriptのコードと共に紹介します。

✨ 点滅エフェクト

CSSとJavaScriptを使って、ランダムな位置に、ランダムな大きさの「きらきら」した要素を点滅させるエフェクトです。アイキャッチや特定のエリアを目立たせたい場合に活用できます。

HTML

まず、エフェクトを表示させたい親要素(箱)を用意し、任意のクラス名(ここでは kirakira_box)を指定します。JavaScriptによって、この要素の内部に点滅する要素(<img>)が動的に追加されます。

<div class="kirakira_box">
  きらきらエフェクト
</div>

CSS (SCSS)

親要素(.kirakira_box)と、JavaScriptで生成される点滅要素(.glitter-star)のスタイルを指定します。.kirakira_box には position: relative; を指定し、点滅要素がこの範囲内を基準に配置されるようにするのがポイントです。

.glitter-star には position: absolute; を指定し、animation プロパティで @keyframes glitter を適用して点滅(出現・消滅)する動きを実現しています。コード内のコメントアウト部分は、位置やサイズを固定・限定したい場合の参考としてご覧ください。

※このコードはSCSSの記法(ネスト、//コメント)を含んでいます。

/* 箱のスタイル */
.kirakira_box {
  padding: 1em; position: relative;
  width: 500px; height: 500px;
  background: #f00; color: gold;
  overflow: hidden; /* 親要素からはみ出さないように追加推奨 */
  img { 
    display: block;
    border-radius: 10px;
		/* CSSでサイズを限定する場合 */
		/*  	min-width: 3%; */
		/*  	max-width: 30%; */
		/* ランダム要素の表示位置を固定する場合 */
		/*			&:nth-child(1) { margin-top: -2%; margin-left: 85%; } */
		/*			&:nth-child(2) { margin-top: 2%; margin-left: 20%;  } */
		/*			... */
  }
}
/* アニメーション */
.glitter-star {
  position: absolute;
  min-width: (30/640)*100%;;
  height: auto;
  opacity: 1;
  /* アニメーションの設定 */
  animation: glitter 5s linear 0s infinite normal;
}

@keyframes glitter {
  0% {
    transform: scale(.5);
    opacity: 0;
  }
  25% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(.5);
    opacity: 0;
  }
  75% {
    transform: scale(1);
    opacity: 1;
  }
  100% {
    transform: scale(.5);
    opacity: 0;
  }
}

JavaScript

指定した数(ここでは for (let i = 0; i < 10; i++)10個)だけ、<img> 要素を生成します。randRange 関数でランダムな幅(width)と位置(top, left)を設定し、setTimeout を使ってランダムな時間差(ramNumber_round)で親要素(.kirakira_box)内に追加しています。これにより、各要素が異なるタイミングで表示され始めます。

/* jQueryが読み込まれている必要があります */
/* もしjQueryを使わない場合、
   $('.kirakira_box').append(el); の部分を
   document.querySelector('.kirakira_box').appendChild(el);
   などに変更してください。
*/

//指定した数だけ星をランダムな順番で出力。
for (let i = 0; i < 10; i++) {
  //ランダムに出力
  const ramNumber_round = parseInt(Math.random() * 5000)
 
	//指定の範囲のランダム出力
	const randRange = function (min, max) {
		return Math.floor(Math.random() * (max - min + 1) + min);
	};
	
  //出力するHTMLタグ
  const el = document.createElement('img');
  
  //imgのソース指定
  el.src = '/images/components/tenmetsu/kirakira-large.png'
  
  //imgのclass名指定		
  el.className = 'glitter-star';
  
  //imgの幅をランダムに指定
  el.style.width = randRange(10,100) + "px";
  
  //0-100 の%でランダムで位置指定
  el.style.top = (randRange(0,100)) + "%";
  el.style.left = (randRange(0,100)) + "%";
  
  //ランダム秒間隔で指定タグ内に要素を出力
  setTimeout(function() {
    $('.kirakira_box').append(el);
  }, ramNumber_round);
}

🌸 桜のエフェクト

こちらは、画面上部から桜の花びらがひらひらと舞い散るようなアニメーションエフェクトです。春先のWebサイトデザインなどにぴったりです。CSSの @keyframes を使って、回転しながら落ちる動きを3種類のパターン(type1type3)で作成しています。

HTML

エフェクトを表示させたい親要素として、id="sakura_box" を持つ <div> 要素をHTMLに配置します。この中にJavaScriptで桜の花びらが生成されます。

<div id="sakura_box"></div>

CSS (SCSS)

親要素(#sakura_box)は、背景や他のコンテンツの邪魔にならないよう position: absolute;z-index: -1; を指定し、pointer-events: none; でクリック操作を透過させています。

JavaScriptで生成される花びら(img)のスタイルと、3種類の落下アニメーション(@keyframes kaiten1, kaiten2, kaiten3)を定義します。アニメーションの forwards は、アニメーション終了時(100% の状態)を保持するために指定されています(この場合、opacity: 0top: 100% が保持されます)。

※このコードもSCSSの記法(ネスト、//コメント)を含んでいます。

/* 桜アニメ */
#sakura_box {
  padding: 1em; 
  position: absolute; top: 0; left: 0; z-index: -1;
  width: 100%; height: 500px;
  /* 背景色はデモ用のため、実際には不要な場合もあります */
  background: red; 
  pointer-events: none;
  overflow: hidden; /* 親要素からはみ出さないように */
  img { 
    display: block;
  	/* アニメ */
  	position: absolute; top: 0; left: auto; right: auto;
  	opacity: 0;
		/* animation: 10s kaiten2 forwards; */
		&.type1 { animation: 10s kaiten1 forwards ; }
		&.type2 { animation: 10s kaiten2 forwards ; }
		&.type3 { animation: 10s kaiten3 .5s forwards ; }
		/* &:nth-child(2n) { animation-delay: .5s; } */
		@keyframes kaiten1 {
			0% { transform:rotate(0); opacity: 0; }
			25% { transform:rotate(360deg); opacity: 1; margin-right: 10% }
			50% { transform:rotate(0deg); opacity: 1; margin-right: 0% }
			75% { transform:rotate(-360deg); margin-right: 10% }
			100% { transform:rotate(0deg); opacity: 0; margin-right: 10%; top: 100%; }
		}
		@keyframes kaiten2 {
			0% { transform:rotate(0); opacity: 0; }
			25% { transform:rotate(360deg); opacity: 1; margin-right: 0% }
			50% { transform:rotate(0deg); opacity: 1; margin-right: 0% }
			75% { transform:rotate(-360deg); margin-right: 0% }
			100% { transform:rotate(0deg); opacity: 0; margin-right: 0%; top: 100%; }
		}
		@keyframes kaiten3 {
			0% { transform:rotate(0); opacity: 0; }
			25% { transform:rotate(360deg); opacity: 1; margin-right: -10% }
			50% { transform:rotate(0deg); opacity: 1; margin-right: 0% }
			75% { transform:rotate(-360deg); margin-right: -10% }
			100% { transform:rotate(0deg); opacity: 0; margin-right: -10%; top: 100%; }
		}
  }
}

JavaScript

kurikaese 関数内で、指定した数(ここでは 15個)の花びら(<img>)を生成します。CSSで定義した type1type3 のクラスを i%3+1 を使って順番に割り当て、ランダムな幅(width)と位置(right)を設定します。

setTimeout でランダムな時間差(ramNumber_round)をつけて花びらを登場させ、さらに10秒後(アニメーション終了とほぼ同時)に removeChild で要素をDOMから削除しています。この処理全体を setInterval で10秒ごとに繰り返すことで、花びらが常に舞い続けるように見せています。

/* 桜エフェクト */
var kurikaese = function(){
	//指定した数だけ星をランダムな順番で出力。
	for (let i = 0; i < 15; i++) {
	  //ランダムに出力
	  const ramNumber_round = parseInt(Math.random() * 10000);
	  //指定の範囲のランダム出力
		var randRange = function (min, max) {
			return Math.floor(Math.random() * (max - min + 1) + min);
		};
	  //出力するHTMLタグ
	  const el = document.createElement('img');
	  //imgのclass名指定
	  //console.log(i%3+1);
	  el.className = 'type'+(i%3+1);
	  //imgのソース指定
	  el.src = '/images/components/tenmetsu/sakura.svg'
	  //imgの幅をランダムに指定
	  el.style.width = randRange(10,26) + "px";
	  //0-100 の%でランダムで位置指定
 	  el.style.right = (randRange(0,100)) + "%";
	  //ランダム地が何かをコンソールで確認
	  //console.log(ramNumber_round / 10 * 2);
	  //ランダム秒間隔で指定タグ内に要素を出力
	  setTimeout(function() {
	    document.getElementById('sakura_box').appendChild(el);
	    //10秒後に要素を消す
		  setTimeout(function() {
			/* 要素が存在する場合のみ削除処理を行う */
			if(el.parentNode) {
				el.parentNode.removeChild(el);
			}
		  }, 10000);
	  }, ramNumber_round);
	}
}//kurikaese
//処理を実行
kurikaese();
//処理を10秒ごとに繰り返す
setInterval(function() {
	kurikaese();
}, 10000);
/*end_桜エフェクト*/

よくある質問(FAQ)

Q1. 画像のパス(`src`)を変更したい場合はどうすればよいですか?

A1. JavaScriptコード内の el.src = '...' となっている部分を、あなたが使用したい画像の正しいパスに変更してください。点滅エフェクトでは '/images/components/tenmetsu/kirakira-large.png'、桜のエフェクトでは '/images/components/tenmetsu/sakura.svg' となっている箇所です。

Q2. エフェクトの要素の数(量)を変更するにはどうすればよいですか?

A2. JavaScriptコード内の for ループの条件式にある数字を変更します。点滅エフェクトでは for (let i = 0; i < 10; i++)10 を、桜のエフェクトでは for (let i = 0; i < 15; i++)15 を、お好みの数(増やしたり減らしたり)に変更してください。

Q3. SCSS(Sass)を使っていなくても、このCSSコードは使えますか?

A3. 記事内のCSS (SCSS)コードには、ネスト(入れ子構造、例:.kirakira_box { img { ... } })や // コメントが含まれています。これらはSCSSの記法ですので、そのままでは通常のCSSとして認識されません。お使いの環境でSCSSをコンパイルできない場合は、ネストを展開し(例:.kirakira_box img { ... })、コメントを /* ... */ 形式に書き直す必要があります。

CONTACT

webサイト制作、デザインに関するご相談、御見積のご依頼など、弊社へのお問い合わせはこちら