スクロールに連動してフェードイン表示などを実行するときのコードです。
HTML
<div class="p-animationTest js-loadAnime --fadeIn">
<div class="p-animationTest__section">
<strong class="js-loadAnime --fadeUp" data-before="animation">fade up</strong>
</div>
<div class="p-animationTest__section">
<strong class="js-scrollAnime --fadeIn" data-before="animation">fade in</strong>
</div>
<div class="p-animationTest__section">
<strong class="js-scrollAnime --zoomIn" data-before="animation">zoom in</strong>
</div>
<div class="p-animationTest__section">
<strong class="js-scrollAnime --blur" data-before="animation">blur</strong>
</div>
<div class="p-animationTest__section">
<strong class="js-scrollAnime --slideIn" data-before="animation">slide in</strong>
</div>
</div>
CSS(Scss)
/*======================
animations
======================*/
$animation-function: ease;
$animation-time: 500ms;
// フェードイン
@keyframes fadeInAnime {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@mixin fadeIn($delay: 100ms) {
opacity: 0;
&.is-animated {
animation-name: fadeInAnime;
animation-fill-mode: forwards;
animation-duration: $animation-time;
animation-iteration-count: 1;
animation-timing-function: $animation-function;
animation-delay: $delay;
animation-direction: normal;
}
}
// フェードインアップ
@keyframes fadeUpAnime {
0% {
opacity: 0;
transform: translateY(100px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
@mixin fadeUp($delay: 100ms) {
opacity: 0;
&.is-animated {
animation-name: fadeUpAnime;
animation-fill-mode: forwards;
animation-duration: $animation-time;
animation-iteration-count: 1;
animation-timing-function: $animation-function;
animation-delay: $delay;
animation-direction: normal;
}
}
// ズームイン
@keyframes zoomInAnime {
0% {
opacity: 0;
transform: scale(0.6);
}
100% {
opacity: 1;
transform: scale(1);
}
}
@mixin zoomIn($delay: 100ms) {
opacity: 0;
&.is-animated {
animation-name: zoomInAnime;
animation-fill-mode: forwards;
animation-duration: $animation-time;
animation-iteration-count: 1;
animation-timing-function: $animation-function;
animation-delay: $delay;
animation-direction: normal;
}
}
// ブラー
@keyframes blurAnime {
0% {
filter: blur(10px);
opacity: 0;
}
100% {
filter: blur(0);
opacity: 1;
}
}
@mixin blur($delay: 100ms) {
opacity: 0;
&.is-animated {
animation-name: blurAnime;
animation-fill-mode: forwards;
animation-duration: $animation-time;
animation-iteration-count: 1;
animation-timing-function: $animation-function;
animation-delay: $delay;
animation-direction: normal;
}
}
// スライドイン
@keyframes slideInAnime {
0% {
opacity: 0;
transform: translateX(-100px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
@mixin slideIn($delay: 100ms) {
opacity: 0;
&.is-animated {
animation-name: slideInAnime;
animation-fill-mode: forwards;
animation-duration: $animation-time;
animation-iteration-count: 1;
animation-timing-function: $animation-function;
animation-delay: $delay;
animation-direction: normal;
}
}
/*======================
animations(JSクラス付与)
======================*/
// ロードしたらアニメーション
.js-loadAnime {
&.--fadeIn {
@include fadeIn(0);
}
&.--fadeUp {
@include fadeUp(0);
}
&.--zoomIn {
@include zoomIn(0);
}
&.--blur {
@include blur(0);
}
&.--slideIn {
@include slideIn(0);
}
}
// 画面に表示されたらアニメーション
.js-scrollAnime {
&.--fadeIn {
@include fadeIn(0);
}
&.--fadeUp {
@include fadeUp(0);
}
&.--zoomIn {
@include zoomIn(0);
}
&.--blur {
@include blur(0);
}
&.--slideIn {
@include slideIn(0);
}
}
/*======================
contents
======================*/
.p-animationTest {
&__section {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: max(568px, 100dvh);
padding: 1.5em;
background: lightblue;
&:nth-child(odd) {
background: skyblue;
}
&:not(:last-child) {
border-bottom: 1px solid #FFF;
}
strong {
font-family: 'Arial Black', sans-serif;
font-size: 80px;
text-transform: capitalize;
mix-blend-mode: overlay;
&::before {
content: attr(data-before);
display: block;
width: fit-content;
margin: 0 auto 0.2em;
font-size: 0.2em;
letter-spacing: 0.1em;
color: #555;
}
}
&:first-child strong.js-loadAnime.--fadeUp.is-animated {
animation-delay: $animation-time + 100ms;
}
}
}
JavaScript
// const
const viewHeight = window.innerHeight;
// ロードしたらアニメーション
var loadAnimeTargets = document.querySelectorAll('.js-loadAnime');
window.addEventListener('load', function () {
for (let target of loadAnimeTargets) {
target.classList.add('is-animated');
}
});
// 画面に表示されたらアニメーション
var scrollAnimeTargets = document.querySelectorAll('.js-scrollAnime');
window.addEventListener('scroll', function () {
var scroll = window.scrollY;
for (let target of scrollAnimeTargets) {
var targetPos = target.getBoundingClientRect().top + scroll + 200;
if (scroll > targetPos - viewHeight) {
target.classList.add('is-animated');
}
}
});
以下のページで動作確認できます。
HTMLでの記述
ロード完了時にアニメーションさせたい要素にクラスを付与します。
ロードしたらアニメーションをする場合のクラス
js-loadAnime
画面に表示されたらアニメーションをする場合のクラス
js-scrollAnime
アニメーションの種類は–fadeUpなどのモディファイアクラスを付与して指定します。
今回作成したアニメーションの種類は以下の5種類です。
- フェードイン(–fadeIn)
- フェードインアップ(–fadeInUp)
- ズームイン(–zoomIn)
- ブラー(–blur)
- スライドイン(–slideIn)
CSSでの記述
各アニメーションの記述は@keyframesと@mixinで管理しています。
アニメーションの周期や時間を変更したい場合は以下の変数を編集。
$animation-function: ease; // 周期
$animation-time: 500ms; // 時間
アニメーションのタイミングについては、指定したい要素ごとに個別で指定していくようにしています。
&:first-child strong.js-loadAnime.--fadeUp.is-animated {
animation-delay: $animation-time + 100ms;
}
JavaScriptでの記述
ロードもしくはスクロールで表示された際に、HTMLで予め指定したクラスにis-animatedクラスを付与することで、CSSで指定したアニメーションが動作する仕組みです。
個別に特別なアニメーションを付与したい場合は、該当箇所の固有のクラス名に大して別途アニメーションを指定することも可能です。
以下の記述の「200」がアニメーションが発動する位置からのオフセットになりますので、こちらでis-animatedクラスが付与される位置を調整してください。
var targetPos = target.getBoundingClientRect().top + scroll + 200;
// ウィンドウの高さを取得
const viewHeight = window.innerHeight;
// ページの読み込みが完了したら、loadAnimeTargetsに対してis-animatedクラスを追加します
var loadAnimeTargets = document.querySelectorAll('.js-loadAnime');
window.addEventListener('load', function () {
for (let target of loadAnimeTargets) {
target.classList.add('is-animated');
}
});
// スクロール位置が、scrollAnimeTargetsが表示される位置を超えた場合にis-animatedクラスを追加します
var scrollAnimeTargets = document.querySelectorAll('.js-scrollAnime');
window.addEventListener('scroll', function () { // ページがスクロールされるたびに実行する
var scroll = window.scrollY; // 現在のスクロール位置
for (let target of scrollAnimeTargets) {
// アニメーションの対象要素の表示位置を計算
/*
getBoundingClientRect():対象要素の位置やサイズ情報を取得
topプロパティ:要素の上端からの距離
scroll:現在のスクロール位置
200:アニメーションが発動する位置からのオフセット
*/
var targetPos = target.getBoundingClientRect().top + scroll + 200;
// スクロール位置がアニメーションの対象要素が表示される位置を超えたか判定
if (scroll > targetPos - viewHeight) {
target.classList.add('is-animated');
}
}
});
- PR