JavaScriptでスクロール位置を管理して、対象要素が画面上に表示されたらclassを追加して、CSS3のアニメーションを行う処理を実装してみます。
サンプルコード
スクロールで対象要素が表示されたら、フェードインしながら下から上に表示するアニメーションを実装してみます。
HTML
画像とテキストを左右に配置するレイアウトで、アニメーションさせる要素に対して.animation-scrollUp を追加しています。
<div class="image-block image-block_left"> <div class="image-block_inner"> <div class="image-block_img"> <img src="./img01.jpg" width="450" alt="" class="animation-scrollUp" /> </div> <div class="image-block_text"> <p class="image-block_ttl animation-scrollUp">キャッチコピー的なテキスト</p> <p class="image-block_description animation-scrollUp">キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。<br /> キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。</p> </div> </div> </div> <div class="image-block image-block_right"> <div class="image-block_inner"> <div class="image-block_img"> <img src="./img02.jpg" width="450" alt="" class="animation-scrollUp" /> </div> <div class="image-block_text"> <p class="image-block_ttl animation-scrollUp">キャッチコピー的なテキスト</p> <p class="image-block_description animation-scrollUp">キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。<br /> キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。</p> </div> </div> </div> <div class="image-block image-block_left"> <div class="image-block_inner"> <div class="image-block_img"> <img src="./img03.jpg" width="450" alt="" class="animation-scrollUp" /> </div> <div class="image-block_text"> <p class="image-block_ttl animation-scrollUp">キャッチコピー的なテキスト</p> <p class="image-block_description animation-scrollUp">キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。<br /> キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。</p> </div> </div> </div> <div class="image-block image-block_right"> <div class="image-block_inner"> <div class="image-block_img"> <img src="./img04.jpg" width="450" alt="" class="animation-scrollUp" /> </div> <div class="image-block_text"> <p class="image-block_ttl animation-scrollUp">キャッチコピー的なテキスト</p> <p class="image-block_description animation-scrollUp">キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。<br /> キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。</p> </div> </div> </div>
CSS
まずはレイアウトを行っている部分のCSSです。
/* 要素配置のスタイル */
.image-block {
padding: 150px 0;
overflow: hidden;
}
.image-block_left {
background: #ecf0f1;
}
.image-block_right {
background: #cfe9fa;
}
.image-block_inner {
width: 1000px;
margin: 0 auto;
}
.image-block_img {
}
.image-block_left .image-block_img {
float: left;
}
.image-block_right .image-block_img {
float: right;
}
.image-block_text {
width: 500px;
}
.image-block_left .image-block_text {
float: right;
}
.image-block_right .image-block_text {
float: left;
}
.image-block_ttl {
color: #3498DB;
font-size: 32px;
margin-bottom: 20px;
}
.image-block_description {
line-height: 1.8;
}
CSS
アニメーション部分のCSSです。
アニメーションはtransitionで行っていて、.is-animatedが追加されたタイミングでtransformとopacityの値を変更するようにしています。
/* アニメーションのスタイル */
.animation-scrollUp {
-webkit-transform: translateY(40px);
transform: translateY(40px);
opacity: 0;
-webkit-transition: 0.8s;
transition: 0.8s;
}
.animation-scrollUp.is-animated {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
JavaScript
スクロール毎に対象要素が画面内に表示されたかどうかを確認して、表示されている場合はclassを追加してアニメーションを実行させています。
$(function() {
$(window).on('load scroll', function() {
setAnimationClass();
});
var animationClass = 'animation-scrollUp'; // アニメーション対象のclass名
var animationFinClass = 'is-animated'; // アニメーションが実行時に付与するclass名
var animationStartPosition = 0.75; // アニメーションが実行されるスクロール位置
// アニメーションが完了しているかどうかを管理する配列
var animationFlagArr = [];
for(var i = 0; i < $('.' + animationClass).length; i++) {
animationFlagArr[i] = false;
}
function setAnimationClass() {
// アニメーションの実行前に、アニメーション完了済の要素を確認しておく
for(var i = 0; i < $('.' + animationClass).length; i++) {
if($('.' + animationClass).eq(i).hasClass(animationFinClass)) {
animationFlagArr[i] = true;
}
}
// スクロール位置と画面高さを取得
var scrollTop = $(window).scrollTop();
var windowHeight = $(window).height();
// アニメーション対象要素が開始位置までスクロールしている場合、classを付与する
for(var i = 0; i < animationFlagArr.length; i++) {
if(animationFlagArr[i] == false) {
var thisElement = $('.' + animationClass).eq(i);
var thisTop = thisElement.offset().top;
if(scrollTop + (windowHeight * animationStartPosition) > thisTop) {
thisElement.addClass(animationFinClass);
}
}
}
}
});
サンプルコード2
テキストを1文字ずつ分解してアニメーションさせてみます。
HTML
基本的には先ほどと同じ構造で、アニメーションさせる要素に対して.animation-scrollRotateを追加しています。
<div class="image-block image-block_left"> <div class="image-block_inner"> <div class="image-block_img"> <img src="./img01.jpg" width="450" alt="" /> </div> <div class="image-block_text"> <p class="image-block_ttl animation-scrollRotate">キャッチコピー的なテキスト</p> <p class="image-block_description">キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。<br /> キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。</p> </div> </div> </div> <div class="image-block image-block_right"> <div class="image-block_inner"> <div class="image-block_img"> <img src="./img02.jpg" width="450" alt="" /> </div> <div class="image-block_text"> <p class="image-block_ttl animation-scrollRotate">キャッチコピー的なテキスト</p> <p class="image-block_description">キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。<br /> キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。</p> </div> </div> </div> <div class="image-block image-block_left"> <div class="image-block_inner"> <div class="image-block_img"> <img src="./img03.jpg" width="450" alt="" /> </div> <div class="image-block_text"> <p class="image-block_ttl animation-scrollRotate">キャッチコピー的なテキスト</p> <p class="image-block_description">キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。<br /> キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。</p> </div> </div> </div> <div class="image-block image-block_right"> <div class="image-block_inner"> <div class="image-block_img"> <img src="./img04.jpg" width="450" alt="" /> </div> <div class="image-block_text"> <p class="image-block_ttl animation-scrollRotate">キャッチコピー的なテキスト</p> <p class="image-block_description">キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。<br /> キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。</p> </div> </div> </div>
CSS
アニメーションは.animation-scrollRotateではなく、その子要素のspanに対して設定しています。
/* アニメーションのスタイル */
.animation-scrollRotate span {
display: inline-block;
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
opacity: 0;
-webkit-transition: 0.8s;
transition: 0.8s;
-webkit-transition-property: transform, opacity;
transition-property: transform, opacity;
}
.animation-scrollRotate.is-animated span {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
opacity: 1;
}
JavaScript
アニメーション部分は先ほどとほぼ同じですが、最初に対象要素のテキストを1文字ずつ分解してspanで括るようにしています。
$(function() {
$(window).on('load scroll', function() {
setAnimationClass();
});
var animationClass = 'animation-scrollRotate'; // アニメーション対象のclass名
var animationFinClass = 'is-animated'; // アニメーションが実行時に付与するclass名
var animationStartPosition = 0.75; // アニメーションが実行されるスクロール位置
// アニメーションが完了しているかどうかを管理する配列
var animationFlagArr = [];
for(var i = 0; i < $('.' + animationClass).length; i++) {
animationFlagArr[i] = false;
var thisText = $('.' + animationClass).eq(i).text().split('');
var animationTextInsert = '';
for(var j = 0; j < thisText.length; j++) {
animationTextInsert += '<span>' + thisText[j] + '</span>'
}
$('.' + animationClass).eq(i).html(animationTextInsert);
}
function setAnimationClass() {
// アニメーションの実行前に、アニメーション完了済の要素を確認しておく
for(var i = 0; i < $('.' + animationClass).length; i++) {
if($('.' + animationClass).eq(i).hasClass(animationFinClass)) {
animationFlagArr[i] = true;
}
}
// スクロール位置と画面高さを取得
var scrollTop = $(window).scrollTop();
var windowHeight = $(window).height();
// アニメーション対象要素が開始位置までスクロールしている場合、classを付与する
for(var i = 0; i < animationFlagArr.length; i++) {
if(animationFlagArr[i] == false) {
var thisElement = $('.' + animationClass).eq(i);
var thisTop = thisElement.offset().top;
if(scrollTop + (windowHeight * animationStartPosition) > thisTop) {
thisElement.addClass(animationFinClass);
}
}
}
}
});
アニメーションのタイミングを1文字ずつずらしたい場合、1文字ずつtransition-delayをずらして設定します。
CSS
/* アニメーションのスタイル */
.animation-scrollRotate span {
display: inline-block;
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
opacity: 0;
-webkit-transition: 0.8s;
transition: 0.8s;
-webkit-transition-property: transform, opacity;
transition-property: transform, opacity;
}
.animation-scrollRotate.is-animated span {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
opacity: 1;
}
.animation-scrollRotate span:nth-child(2) {-webkit-transition-delay: 0.1s;transition-delay: 0.1s;}
.animation-scrollRotate span:nth-child(3) {-webkit-transition-delay: 0.2s;transition-delay: 0.2s;}
.animation-scrollRotate span:nth-child(4) {-webkit-transition-delay: 0.3s;transition-delay: 0.3s;}
.animation-scrollRotate span:nth-child(5) {-webkit-transition-delay: 0.4s;transition-delay: 0.4s;}
.animation-scrollRotate span:nth-child(6) {-webkit-transition-delay: 0.5s;transition-delay: 0.5s;}
.animation-scrollRotate span:nth-child(7) {-webkit-transition-delay: 0.6s;transition-delay: 0.6s;}
.animation-scrollRotate span:nth-child(8) {-webkit-transition-delay: 0.7s;transition-delay: 0.7s;}
.animation-scrollRotate span:nth-child(9) {-webkit-transition-delay: 0.8s;transition-delay: 0.8s;}
.animation-scrollRotate span:nth-child(10) {-webkit-transition-delay: 0.9s;transition-delay: 0.9s;}
.animation-scrollRotate span:nth-child(11) {-webkit-transition-delay: 1.0s;transition-delay: 1.0s;}
.animation-scrollRotate span:nth-child(12) {-webkit-transition-delay: 1.1s;transition-delay: 1.1s;}
.animation-scrollRotate span:nth-child(13) {-webkit-transition-delay: 1.2s;transition-delay: 1.2s;}
.animation-scrollRotate span:nth-child(14) {-webkit-transition-delay: 1.3s;transition-delay: 1.3s;}
.animation-scrollRotate span:nth-child(15) {-webkit-transition-delay: 1.4s;transition-delay: 1.4s;}
一文字ずつタイミングをずらしてアニメーションさせるデモページ
サンプルコード3
アニメーションの種類を複数設定してみます。
HTML
画像、タイトル、本文のそれぞれでアニメーションを変更してみます。
それぞれ.animation-scrollScale、.animation-scrollRotate、animation-scrollUpとclassを追加しています。
<div class="image-block image-block_left"> <div class="image-block_inner"> <div class="image-block_img"> <img src="./img01.jpg" width="450" alt="" class="animation-scrollScale" /> </div> <div class="image-block_text"> <p class="image-block_ttl animation-scrollRotate">キャッチコピー的なテキスト</p> <p class="image-block_description animation-scrollUp">キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。<br /> キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。</p> </div> </div> </div> <div class="image-block image-block_right"> <div class="image-block_inner"> <div class="image-block_img"> <img src="./img02.jpg" width="450" alt="" class="animation-scrollScale" /> </div> <div class="image-block_text"> <p class="image-block_ttl animation-scrollRotate">キャッチコピー的なテキスト</p> <p class="image-block_description animation-scrollUp">キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。<br /> キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。</p> </div> </div> </div> <div class="image-block image-block_left"> <div class="image-block_inner"> <div class="image-block_img"> <img src="./img03.jpg" width="450" alt="" class="animation-scrollScale" /> </div> <div class="image-block_text"> <p class="image-block_ttl animation-scrollRotate">キャッチコピー的なテキスト</p> <p class="image-block_description animation-scrollUp">キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。<br /> キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。</p> </div> </div> </div> <div class="image-block image-block_right"> <div class="image-block_inner"> <div class="image-block_img"> <img src="./img04.jpg" width="450" alt="" class="animation-scrollScale" /> </div> <div class="image-block_text"> <p class="image-block_ttl animation-scrollRotate">キャッチコピー的なテキスト</p> <p class="image-block_description animation-scrollUp">キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。<br /> キャッチコピーに対する説明文が入ります。キャッチコピーに対する説明文が入ります。</p> </div> </div> </div>
CSS
transitionを使ってアニメーションを設定しています。
/* アニメーションのスタイル */
.animation-scrollUp {
-webkit-transform: translateY(40px);
transform: translateY(40px);
opacity: 0;
-webkit-transition: 0.8s;
transition: 0.8s;
}
.animation-scrollUp.is-animated {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
.animation-scrollRotate span {
display: inline-block;
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
opacity: 0;
-webkit-transition: 0.8s;
transition: 0.8s;
-webkit-transition-property: transform, opacity;
transition-property: transform, opacity;
}
.animation-scrollRotate.is-animated span {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
opacity: 1;
}
.animation-scrollRotate span:nth-child(2) {-webkit-transition-delay: 0.1s;transition-delay: 0.1s;}
.animation-scrollRotate span:nth-child(3) {-webkit-transition-delay: 0.2s;transition-delay: 0.2s;}
.animation-scrollRotate span:nth-child(4) {-webkit-transition-delay: 0.3s;transition-delay: 0.3s;}
.animation-scrollRotate span:nth-child(5) {-webkit-transition-delay: 0.4s;transition-delay: 0.4s;}
.animation-scrollRotate span:nth-child(6) {-webkit-transition-delay: 0.5s;transition-delay: 0.5s;}
.animation-scrollRotate span:nth-child(7) {-webkit-transition-delay: 0.6s;transition-delay: 0.6s;}
.animation-scrollRotate span:nth-child(8) {-webkit-transition-delay: 0.7s;transition-delay: 0.7s;}
.animation-scrollRotate span:nth-child(9) {-webkit-transition-delay: 0.8s;transition-delay: 0.8s;}
.animation-scrollRotate span:nth-child(10) {-webkit-transition-delay: 0.9s;transition-delay: 0.9s;}
.animation-scrollRotate span:nth-child(11) {-webkit-transition-delay: 1.0s;transition-delay: 1.0s;}
.animation-scrollRotate span:nth-child(12) {-webkit-transition-delay: 1.1s;transition-delay: 1.1s;}
.animation-scrollRotate span:nth-child(13) {-webkit-transition-delay: 1.2s;transition-delay: 1.2s;}
.animation-scrollRotate span:nth-child(14) {-webkit-transition-delay: 1.3s;transition-delay: 1.3s;}
.animation-scrollRotate span:nth-child(15) {-webkit-transition-delay: 1.4s;transition-delay: 1.4s;}
.animation-scrollScale {
-webkit-transform: scale(1.2);
transform: scale(1.2);
opacity: 0;
-webkit-transition: 0.8s;
transition: 0.8s;
}
.animation-scrollScale.is-animated {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1;
}
JavaScript
classなどを配列で管理するように変更して、複数のclassを設定できるように変更しています。
タイトル部分だけ1文字ずつアニメーションさせるため、19~28行目でspanを追加しています。
$(function() {
$(window).on('load scroll', function() {
setAnimationClass();
});
var animationClassArr = ['animation-scrollUp', 'animation-scrollRotate', 'animation-scrollScale']; // アニメーション対象のclass名
var animationFinClassArr = ['is-animated', 'is-animated', 'is-animated']; // アニメーションが実行時に付与するclass名
var animationStartPositionArr = [0.75, 0.75, 0.75]; // アニメーションが実行されるスクロール位置
// アニメーションが完了しているかどうかを管理する配列
var animationFlagArr = {};
for(var i = 0; i < animationClassArr.length; i++) {
animationFlagArr[animationClassArr[i]] = [];
for(var j = 0; j < $('.' + animationClassArr[i]).length; j++) {
animationFlagArr[animationClassArr[i]][j] = false;
}
}
// .animation-scrollRotateのテキストにspan追加
for(var i = 0; i < $('.' + animationClassArr[1]).length; i++) {
var thisElem = $('.' + animationClassArr[1]).eq(i);
var thisText = thisElem.text().split('');
var animationTextInsert = '';
for(var j = 0; j < thisText.length; j++) {
animationTextInsert += '<span>' + thisText[j] + '</span>'
}
thisElem.html(animationTextInsert);
}
function setAnimationClass() {
// アニメーションの実行前に、アニメーション完了済の要素を確認しておく
for(var i = 0; i < animationClassArr.length; i++) {
for(var j = 0; j < $('.' + animationClassArr[i]).length; j++) {
if($('.' + animationClassArr[i]).eq(j).hasClass(animationFinClassArr[i])) {
animationFlagArr[animationClassArr[i]][j] = true;
}
}
}
// スクロール位置と画面高さを取得
var scrollTop = $(window).scrollTop();
var windowHeight = $(window).height();
// アニメーション対象要素が開始位置までスクロールしている場合、classを付与する
for(var i = 0; i < animationClassArr.length; i++) {
for(var j = 0; j < animationFlagArr[animationClassArr[i]].length; j++) {
if(animationFlagArr[animationClassArr[i]][j] == false) {
var thisElement = $('.' + animationClassArr[i]).eq(j);
var thisTop = thisElement.offset().top;
if(scrollTop + (windowHeight * animationStartPositionArr[i]) > thisTop) {
thisElement.addClass(animationFinClassArr[i]);
}
}
}
}
}
});
コメントが承認されるまで時間がかかります。