2026年5月20日
2026年5月20日
WordPressでスクロールアニメーションを実装する方法
はじめに
スクロールアニメーションは、要素がビューポートに入ったタイミングでフェードインやスライドインするエフェクトです。Intersection Observer API を使うことでパフォーマンスを確保しながら実装できます。
症状・原因
- スクロールしたら要素がフワっと表示されるようにしたい
- 要素が画面に入ったタイミングでアニメーションさせたい
- スクロールイベントを使わずにパフォーマンス良く実装したい
- 遅延アニメーションで要素を順番に表示したい
解決手順
ステップ1:CSSでアニメーション定義
/* style.css — アニメーション定義 */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeInLeft {
from { opacity: 0; transform: translateX(-30px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* 初期状態(非表示) */
[data-animate] {
opacity: 0;
}
/* アニメーション実行(Intersection Observer が付与) */
[data-animate].is-animated {
animation-fill-mode: both;
animation-duration: 0.6s;
animation-timing-function: ease-out;
}
[data-animate="fade-up"].is-animated { animation-name: fadeInUp; }
[data-animate="fade-left"].is-animated { animation-name: fadeInLeft; }
[data-animate="fade-in"].is-animated { animation-name: fadeIn; }
/* アニメーション遅延(順番に表示) */
[data-delay="100"].is-animated { animation-delay: 0.1s; }
[data-delay="200"].is-animated { animation-delay: 0.2s; }
[data-delay="300"].is-animated { animation-delay: 0.3s; }
/* prefers-reduced-motion 対応 */
@media (prefers-reduced-motion: reduce) {
[data-animate] { opacity: 1; }
[data-animate].is-animated { animation: none; }
}
ステップ2:Intersection Observer で実装
// js/scroll-animation.js
document.addEventListener('DOMContentLoaded', function() {
const observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
entry.target.classList.add('is-animated');
// 一度表示したら監視を停止(パフォーマンス最適化)
observer.unobserve(entry.target);
}
});
}, {
threshold: 0.1, // 10%見えたらトリガー
rootMargin: '0px 0px -50px 0px' // 画面下50px手前でトリガー
});
// data-animate 属性を持つ要素を全て監視
document.querySelectorAll('[data-animate]').forEach(function(el) {
observer.observe(el);
});
});
ステップ3:テンプレートでの使い方
// template-parts/content.php — 記事カードにアニメーション適用
<article data-animate="fade-up" data-delay="<?= ($index % 3) * 100 ?>">
<?php the_title('<h2>', '</h2>'); ?>
<?php the_excerpt(); ?>
</article>
<!-- HTMLで直接使う場合 -->
<section data-animate="fade-in">
<h2>セクション見出し</h2>
</section>
<div class="card-grid">
<div data-animate="fade-up" data-delay="0">カード1</div>
<div data-animate="fade-up" data-delay="100">カード2</div>
<div data-animate="fade-up" data-delay="200">カード3</div>
</div>
ステップ4:Gutenbergブロックに自動でアニメーションを追加
// functions.php — 特定ブロックに自動でdata-animate属性を追加
add_filter('render_block', function(string $html, array $block): string {
$animate_blocks = [
'core/heading' => 'fade-up',
'core/image' => 'fade-in',
'core/group' => 'fade-up',
'core/columns' => 'fade-up',
];
if (!isset($animate_blocks[$block['blockName']])) return $html;
$type = $animate_blocks[$block['blockName']];
// 先頭のタグにdata-animate属性を追加
return preg_replace('/^(<\w+)/', '$1 data-animate="' . $type . '"', $html, 1);
}, 10, 2);
ステップ5:スクリプトのエンキュー
// functions.php
add_action('wp_enqueue_scripts', function(): void {
wp_enqueue_script(
'scroll-animation',
get_template_directory_uri() . '/js/scroll-animation.js',
[],
filemtime(get_template_directory() . '/js/scroll-animation.js'),
true
);
});
注意事項
Intersection ObserverはIE11以外の全モダンブラウザで対応しています。IE11対応が必要な場合はpolyfillを使用してください@media (prefers-reduced-motion: reduce)で動きを抑える設定のユーザーにはアニメーションを無効化してください。アクセシビリティ上の重要な対応です- アニメーション済みの要素は
observer.unobserve()で監視を停止することでメモリとCPUを節約できます
まとめ
Intersection Observer の isIntersecting で要素がビューポートに入ったことを検知し、is-animated クラスを付与してCSSアニメーションを発火させます。data-animate="fade-up" と data-delay="100" で種類と遅延を指定できます。prefers-reduced-motion への対応も忘れずに。