gsap-animations
WebデザインにおけるGSAPアニメーション実装・レビュー時に、スクロールトリガー、パフォーマンス最適化、アクセシビリティ、レスポンシブ対応、テスト統合などのベストプラクティスを考慮し、高品質なアニメーションをWordPress等に実装するSkill。
📜 元の英語説明(参考)
GSAP animation best practices for web design - scroll triggers, performance optimization, accessibility, responsive animations, and testing integration. Use when implementing or reviewing animations on WordPress or any web project.
🇯🇵 日本人クリエイター向け解説
WebデザインにおけるGSAPアニメーション実装・レビュー時に、スクロールトリガー、パフォーマンス最適化、アクセシビリティ、レスポンシブ対応、テスト統合などのベストプラクティスを考慮し、高品質なアニメーションをWordPress等に実装するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o gsap-animations.zip https://jpskill.com/download/18116.zip && unzip -o gsap-animations.zip && rm gsap-animations.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/18116.zip -OutFile "$d\gsap-animations.zip"; Expand-Archive "$d\gsap-animations.zip" -DestinationPath $d -Force; ri "$d\gsap-animations.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
gsap-animations.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
gsap-animationsフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
GSAPアニメーションのベストプラクティス
GSAP (GreenSock Animation Platform) を使用して、プロフェッショナルで、アクセシブルで、パフォーマンスの高いアニメーションを実装するための包括的なガイドです。
コア原則
1. パフォーマンス第一
transformとopacityのみをアニメーション化します (GPU アクセラレーション)。width、height、top、left、margin、paddingのアニメーション化は避けます。will-changeは控えめに使用します。- すべてのデバイスで 60fps を目標にします。
2. 常にアクセシビリティ
prefers-reduced-motionを尊重します。- JavaScript なしでコンテンツが表示されるようにします。
- アニメーションの背後に重要なコンテンツを隠さないでください。
- 長いアニメーションのために、スキップ/一時停止コントロールを提供します。
3. プログレッシブエンハンスメント
- コンテンツはアニメーションなしで動作する必要があります。
- アニメーションは機能を強化するものであり、置き換えるものではありません。
- アニメーションを無効にしてテストします。
GSAP のセットアップ
インストール
<!-- CDN (WordPress に推奨) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js"></script>
<!-- オプションのプラグイン -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollSmoother.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/SplitText.min.js"></script>
WordPress エンキュー
function theme_enqueue_gsap() {
// GSAP Core
wp_enqueue_script(
'gsap',
'https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js',
array(),
'3.12.5',
true
);
// ScrollTrigger
wp_enqueue_script(
'gsap-scrolltrigger',
'https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js',
array('gsap'),
'3.12.5',
true
);
// Theme animations
wp_enqueue_script(
'theme-animations',
get_theme_file_uri('/assets/js/animations.js'),
array('gsap', 'gsap-scrolltrigger'),
filemtime(get_theme_file_path('/assets/js/animations.js')),
true
);
}
add_action('wp_enqueue_scripts', 'theme_enqueue_gsap');
アニメーションパターン
1. スクロールでフェードイン
// 基本的なフェードイン
gsap.from('.fade-in', {
opacity: 0,
y: 50,
duration: 1,
stagger: 0.2,
scrollTrigger: {
trigger: '.fade-in',
start: 'top 80%',
toggleActions: 'play none none none'
}
});
2. 段階的な要素
// カードが1つずつ表示される
gsap.from('.card', {
opacity: 0,
y: 100,
duration: 0.8,
stagger: {
amount: 0.6,
from: 'start'
},
ease: 'power2.out',
scrollTrigger: {
trigger: '.cards-container',
start: 'top 75%'
}
});
3. パララックス効果
// 画像の微妙なパララックス
gsap.to('.parallax-image', {
yPercent: -20,
ease: 'none',
scrollTrigger: {
trigger: '.parallax-section',
start: 'top bottom',
end: 'bottom top',
scrub: true
}
});
4. テキストの表示 (行ごと)
// SplitText プラグインが必要 (Club GreenSock)
// または、以下の CSS ベースの代替案を使用してください
// CSS 代替案 - 各行を span でラップする
gsap.from('.reveal-line', {
opacity: 0,
y: '100%',
duration: 0.8,
stagger: 0.1,
ease: 'power3.out',
scrollTrigger: {
trigger: '.text-reveal',
start: 'top 80%'
}
});
5. カーテン/マスクの表示
// スライドマスクで画像を表示
gsap.to('.curtain-mask', {
scaleX: 0,
transformOrigin: 'right center',
duration: 1.2,
ease: 'power4.inOut',
scrollTrigger: {
trigger: '.curtain-container',
start: 'top 70%'
}
});
6. ヒーローアニメーションタイムライン
// 複雑なヒーローシーケンス
const heroTL = gsap.timeline({
defaults: { ease: 'power3.out' }
});
heroTL
.from('.hero-bg', { scale: 1.2, duration: 1.5 })
.from('.hero-title', { opacity: 0, y: 100, duration: 1 }, '-=1')
.from('.hero-subtitle', { opacity: 0, y: 50, duration: 0.8 }, '-=0.5')
.from('.hero-cta', { opacity: 0, y: 30, duration: 0.6 }, '-=0.3');
アクセシビリティ
縮小モーションの尊重
// ユーザー設定の確認
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
// オプション 1: すべてのアニメーションを無効にする
if (prefersReducedMotion) {
gsap.globalTimeline.timeScale(0);
ScrollTrigger.getAll().forEach(st => st.kill());
}
// オプション 2: 簡略化されたアニメーション
const animationConfig = prefersReducedMotion
? { duration: 0, stagger: 0 }
: { duration: 1, stagger: 0.2 };
gsap.from('.element', {
opacity: 0,
y: prefersReducedMotion ? 0 : 50,
...animationConfig
});
CSS フォールバック
/* JSなしでもコンテンツが表示されるようにする */
.fade-in {
opacity: 1;
transform: translateY(0);
}
/* アニメーションが実行される場合にのみ非表示にする */
.js .fade-in {
opacity: 0;
transform: translateY(50px);
}
/* CSSでも縮小モーションを尊重する */
@media (prefers-reduced-motion: reduce) {
.js .fade-in {
opacity: 1;
transform: none;
}
}
HTML に JS クラスを追加
// スクリプトの先頭に追加
document.documentElement.classList.add('js');
レスポンシブアニメーション
ブレークポイントを意識したアニメーション
// レスポンシブアニメーションを作成
const mm = gsap.matchMedia();
mm.add('(min-width: 1024px)', () => {
// デスクトップアニメーション
gsap.from('.hero-image', {
x: 100,
opacity: 0,
duration: 1.2
});
return () => {
// ブレークポイント変更時のクリーンアップ
};
});
mm.add('(max-width: 1023px)', () => {
// モバイルアニメーション (よりシンプル)
gsap.from('.hero-image', {
opacity: 0,
duration: 0.8
});
});
リサイズ時にリフレッシュ
// リサイズ時に ScrollTrigger を再計算
let resizeTimer;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
ScrollTrigger.refresh();
}, 250);
});
Perf
(原文がここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
GSAP Animation Best Practices
Comprehensive guide for implementing professional, accessible, and performant animations using GSAP (GreenSock Animation Platform).
Core Principles
1. Performance First
- Animate
transformandopacityonly (GPU-accelerated) - Avoid animating
width,height,top,left,margin,padding - Use
will-changesparingly - Target 60fps on all devices
2. Accessibility Always
- Respect
prefers-reduced-motion - Ensure content is visible without JavaScript
- Don't hide critical content behind animations
- Provide skip/pause controls for long animations
3. Progressive Enhancement
- Content must work without animations
- Animations enhance, not replace, functionality
- Test with animations disabled
GSAP Setup
Installation
<!-- CDN (recommended for WordPress) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js"></script>
<!-- Optional plugins -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollSmoother.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/SplitText.min.js"></script>
WordPress Enqueue
function theme_enqueue_gsap() {
// GSAP Core
wp_enqueue_script(
'gsap',
'https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js',
array(),
'3.12.5',
true
);
// ScrollTrigger
wp_enqueue_script(
'gsap-scrolltrigger',
'https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js',
array('gsap'),
'3.12.5',
true
);
// Theme animations
wp_enqueue_script(
'theme-animations',
get_theme_file_uri('/assets/js/animations.js'),
array('gsap', 'gsap-scrolltrigger'),
filemtime(get_theme_file_path('/assets/js/animations.js')),
true
);
}
add_action('wp_enqueue_scripts', 'theme_enqueue_gsap');
Animation Patterns
1. Fade In on Scroll
// Basic fade in
gsap.from('.fade-in', {
opacity: 0,
y: 50,
duration: 1,
stagger: 0.2,
scrollTrigger: {
trigger: '.fade-in',
start: 'top 80%',
toggleActions: 'play none none none'
}
});
2. Staggered Elements
// Cards appearing one by one
gsap.from('.card', {
opacity: 0,
y: 100,
duration: 0.8,
stagger: {
amount: 0.6,
from: 'start'
},
ease: 'power2.out',
scrollTrigger: {
trigger: '.cards-container',
start: 'top 75%'
}
});
3. Parallax Effect
// Subtle parallax on images
gsap.to('.parallax-image', {
yPercent: -20,
ease: 'none',
scrollTrigger: {
trigger: '.parallax-section',
start: 'top bottom',
end: 'bottom top',
scrub: true
}
});
4. Text Reveal (Line by Line)
// Requires SplitText plugin (Club GreenSock)
// Or use CSS-based alternative below
// CSS Alternative - wrap each line in a span
gsap.from('.reveal-line', {
opacity: 0,
y: '100%',
duration: 0.8,
stagger: 0.1,
ease: 'power3.out',
scrollTrigger: {
trigger: '.text-reveal',
start: 'top 80%'
}
});
5. Curtain/Mask Reveal
// Image revealed by sliding mask
gsap.to('.curtain-mask', {
scaleX: 0,
transformOrigin: 'right center',
duration: 1.2,
ease: 'power4.inOut',
scrollTrigger: {
trigger: '.curtain-container',
start: 'top 70%'
}
});
6. Hero Animation Timeline
// Complex hero sequence
const heroTL = gsap.timeline({
defaults: { ease: 'power3.out' }
});
heroTL
.from('.hero-bg', { scale: 1.2, duration: 1.5 })
.from('.hero-title', { opacity: 0, y: 100, duration: 1 }, '-=1')
.from('.hero-subtitle', { opacity: 0, y: 50, duration: 0.8 }, '-=0.5')
.from('.hero-cta', { opacity: 0, y: 30, duration: 0.6 }, '-=0.3');
Accessibility
Respect Reduced Motion
// Check user preference
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
// Option 1: Disable all animations
if (prefersReducedMotion) {
gsap.globalTimeline.timeScale(0);
ScrollTrigger.getAll().forEach(st => st.kill());
}
// Option 2: Simplified animations
const animationConfig = prefersReducedMotion
? { duration: 0, stagger: 0 }
: { duration: 1, stagger: 0.2 };
gsap.from('.element', {
opacity: 0,
y: prefersReducedMotion ? 0 : 50,
...animationConfig
});
CSS Fallback
/* Ensure content visible without JS */
.fade-in {
opacity: 1;
transform: translateY(0);
}
/* Only hide if animations will run */
.js .fade-in {
opacity: 0;
transform: translateY(50px);
}
/* Respect reduced motion in CSS too */
@media (prefers-reduced-motion: reduce) {
.js .fade-in {
opacity: 1;
transform: none;
}
}
Add JS Class to HTML
// Add at start of script
document.documentElement.classList.add('js');
Responsive Animations
Breakpoint-Aware Animations
// Create responsive animations
const mm = gsap.matchMedia();
mm.add('(min-width: 1024px)', () => {
// Desktop animations
gsap.from('.hero-image', {
x: 100,
opacity: 0,
duration: 1.2
});
return () => {
// Cleanup on breakpoint change
};
});
mm.add('(max-width: 1023px)', () => {
// Mobile animations (simpler)
gsap.from('.hero-image', {
opacity: 0,
duration: 0.8
});
});
Refresh on Resize
// Recalculate ScrollTrigger on resize
let resizeTimer;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
ScrollTrigger.refresh();
}, 250);
});
Performance Optimization
1. Use Transform Properties Only
// GOOD - GPU accelerated
gsap.to('.element', {
x: 100, // transform: translateX
y: 50, // transform: translateY
rotation: 45, // transform: rotate
scale: 1.2, // transform: scale
opacity: 0.5
});
// BAD - Causes layout/paint
gsap.to('.element', {
left: 100, // Triggers layout
width: '200px', // Triggers layout
marginTop: 50 // Triggers layout
});
2. Batch Similar Animations
// Use batch for many similar elements
ScrollTrigger.batch('.card', {
onEnter: batch => gsap.to(batch, {
opacity: 1,
y: 0,
stagger: 0.1
}),
start: 'top 85%'
});
3. Kill Unused ScrollTriggers
// Cleanup when navigating (SPA) or component unmount
function cleanup() {
ScrollTrigger.getAll().forEach(st => st.kill());
gsap.killTweensOf('*');
}
4. Lazy Initialize
// Only initialize animations for visible sections
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
initSectionAnimations(entry.target);
observer.unobserve(entry.target);
}
});
}, { rootMargin: '100px' });
document.querySelectorAll('.animated-section').forEach(section => {
observer.observe(section);
});
ScrollTrigger Best Practices
1. Proper Start/End Points
// Avoid common mistakes
ScrollTrigger.create({
trigger: '.section',
start: 'top 80%', // When top of trigger hits 80% from top of viewport
end: 'bottom 20%', // When bottom of trigger hits 20% from top
markers: true, // Debug only - remove in production!
});
2. Pin Sections Carefully
// Pinning can cause layout issues
ScrollTrigger.create({
trigger: '.pinned-section',
start: 'top top',
end: '+=100%',
pin: true,
pinSpacing: true, // Usually want this true
anticipatePin: 1 // Helps with mobile
});
3. Handle Images Loading
// Wait for images before calculating positions
ScrollTrigger.config({
ignoreMobileResize: true
});
window.addEventListener('load', () => {
ScrollTrigger.refresh();
});
// Or refresh after lazy images load
document.querySelectorAll('img[loading="lazy"]').forEach(img => {
img.addEventListener('load', () => ScrollTrigger.refresh());
});
Testing Integration
Visual QA Compatibility
For the visual-qa skill to capture animations correctly:
// Expose function to complete all animations instantly
window.completeAllAnimations = function() {
gsap.globalTimeline.progress(1);
ScrollTrigger.getAll().forEach(st => {
st.scroll(st.end);
});
};
// Or skip animations entirely for screenshots
if (window.location.search.includes('skip-animations')) {
gsap.globalTimeline.timeScale(100);
}
Playwright Testing
// In Playwright test
await page.evaluate(() => {
if (window.completeAllAnimations) {
window.completeAllAnimations();
}
});
await page.waitForTimeout(500);
await page.screenshot({ path: 'screenshot.png', fullPage: true });
Common Animation Library
Reusable Animation Classes
// animations.js - Reusable animation library
const Animations = {
// Initialize all animations
init() {
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
return;
}
this.fadeIn();
this.slideIn();
this.parallax();
this.textReveal();
},
fadeIn() {
gsap.utils.toArray('[data-animate="fade-in"]').forEach(el => {
gsap.from(el, {
opacity: 0,
y: 50,
duration: 0.8,
scrollTrigger: {
trigger: el,
start: 'top 85%',
once: true
}
});
});
},
slideIn() {
gsap.utils.toArray('[data-animate="slide-left"]').forEach(el => {
gsap.from(el, {
opacity: 0,
x: -100,
duration: 1,
scrollTrigger: {
trigger: el,
start: 'top 80%',
once: true
}
});
});
gsap.utils.toArray('[data-animate="slide-right"]').forEach(el => {
gsap.from(el, {
opacity: 0,
x: 100,
duration: 1,
scrollTrigger: {
trigger: el,
start: 'top 80%',
once: true
}
});
});
},
parallax() {
gsap.utils.toArray('[data-parallax]').forEach(el => {
const speed = el.dataset.parallax || 0.2;
gsap.to(el, {
yPercent: -100 * speed,
ease: 'none',
scrollTrigger: {
trigger: el.parentElement,
start: 'top bottom',
end: 'bottom top',
scrub: true
}
});
});
},
textReveal() {
gsap.utils.toArray('[data-animate="text-reveal"]').forEach(el => {
const lines = el.querySelectorAll('.line');
gsap.from(lines, {
opacity: 0,
y: '100%',
duration: 0.8,
stagger: 0.1,
scrollTrigger: {
trigger: el,
start: 'top 80%',
once: true
}
});
});
},
// Refresh after dynamic content
refresh() {
ScrollTrigger.refresh();
},
// Cleanup for SPA navigation
destroy() {
ScrollTrigger.getAll().forEach(st => st.kill());
gsap.killTweensOf('*');
}
};
// Initialize on DOM ready
document.addEventListener('DOMContentLoaded', () => Animations.init());
HTML Usage
<!-- Fade in -->
<div data-animate="fade-in">Content</div>
<!-- Slide from left -->
<div data-animate="slide-left">Content</div>
<!-- Parallax (0.2 = 20% speed) -->
<img data-parallax="0.3" src="image.jpg">
<!-- Text reveal (requires line wrapping) -->
<div data-animate="text-reveal">
<div class="line">First line</div>
<div class="line">Second line</div>
</div>
Debugging
Enable Markers
ScrollTrigger.defaults({
markers: true // Shows start/end markers
});
Log Animation Events
gsap.to('.element', {
x: 100,
onStart: () => console.log('Animation started'),
onComplete: () => console.log('Animation completed'),
onUpdate: self => console.log('Progress:', self.progress())
});
Check for Issues
// List all ScrollTriggers
console.log('ScrollTriggers:', ScrollTrigger.getAll());
// Check if element exists
const el = document.querySelector('.animated-element');
if (!el) console.warn('Animation target not found!');
Checklist
Before Launch
- [ ] Remove all
markers: true - [ ] Test with
prefers-reduced-motion: reduce - [ ] Test on mobile devices (real devices, not just DevTools)
- [ ] Check performance in DevTools Performance tab
- [ ] Verify 60fps on target devices
- [ ] Content visible without JavaScript
- [ ] Images lazy-loaded before ScrollTrigger refresh
- [ ] No layout thrashing (avoid animating layout properties)
Visual QA Integration
- [ ] Animations complete before screenshots
- [ ] Full-page scroll triggers all animations
- [ ] Screenshots capture final animated state
- [ ] Test at all viewport sizes