Performance Guidelines
Performance optimization guidelines for FoundryKit animations
Performance Guidelines
Learn how to optimize FoundryKit animations for maximum performance and smooth user experiences.
Animation Performance Best Practices
Use Transform-Based Animations
Prefer transform animations over layout-triggering properties for better performance.
import { FadeIn, SlideUp, Scale } from '@foundrykit/animation'
function OptimizedAnimations() {
return (
<div className="space-y-4">
{/* ✅ Good - Transform-based animations */}
<FadeIn>
<div className="p-4 bg-blue-100 rounded">Fade In (opacity transform)</div>
</FadeIn>
<SlideUp>
<div className="p-4 bg-green-100 rounded">Slide Up (transform: translateY)</div>
</SlideUp>
<Scale>
<div className="p-4 bg-purple-100 rounded">Scale (transform: scale)</div>
</Scale>
</div>
)
}
// ❌ Avoid - Layout-triggering animations
function AvoidLayoutAnimations() {
return (
<div className="space-y-4">
{/* These trigger layout recalculations */}
<div className="animate-width">Width animation</div>
<div className="animate-height">Height animation</div>
<div className="animate-margin">Margin animation</div>
</div>
)
}
Optimize Animation Timing
Use appropriate durations and delays to maintain smooth performance.
import { FadeIn, SlideUp } from '@foundrykit/animation'
function OptimizedTiming() {
return (
<div className="space-y-4">
{/* Fast animations for immediate feedback */}
<FadeIn duration={0.2}>
<button className="px-4 py-2 bg-blue-600 text-white rounded">
Quick Response
</button>
</FadeIn>
{/* Medium animations for content transitions */}
<SlideUp duration={0.4} delay={0.1}>
<div className="p-4 bg-gray-100 rounded">
Content transition
</div>
</SlideUp>
{/* Longer animations for dramatic effects */}
<FadeIn duration={0.8} delay={0.3}>
<div className="p-6 bg-white rounded-lg shadow">
Hero content
</div>
</FadeIn>
</div>
)
}
Memory Management
Cleanup Animations on Unmount
Ensure animations are properly cleaned up to prevent memory leaks.
import { FadeIn } from '@foundrykit/animation'
import { useState, useEffect } from 'react'
function CleanupExample() {
const [isVisible, setIsVisible] = useState(true)
useEffect(() => {
const timer = setTimeout(() => {
setIsVisible(false)
}, 5000)
return () => {
clearTimeout(timer)
// Framer Motion automatically cleans up animations
}
}, [])
if (!isVisible) {
return null
}
return (
<FadeIn>
<div className="p-4 bg-yellow-100 rounded">
This will be cleaned up after 5 seconds
</div>
</FadeIn>
)
}
Limit Concurrent Animations
Avoid running too many animations simultaneously to prevent performance issues.
import { Stagger } from '@foundrykit/animation'
function LimitedConcurrentAnimations() {
const items = Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`)
return (
<div className="space-y-2">
{/* Limit visible animations */}
<Stagger
animation="slideUp"
staggerDelay={0.05} // Faster stagger for better performance
maxVisible={10 // Only animate visible items
>
{items.map((item, index) => (
<div key={index} className="p-2 bg-gray-100 rounded">
{item}
</div>
))}
</Stagger>
</div>
)
}
Accessibility and Performance
Respect Reduced Motion Preferences
Always respect user preferences for reduced motion.
import { FadeIn, SlideUp } from '@foundrykit/animation'
import { useMediaQuery } from '@foundrykit/hooks'
function AccessibleAnimations() {
const prefersReducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)')
if (prefersReducedMotion) {
return (
<div className="space-y-4">
{/* No animations for users who prefer reduced motion */}
<div className="p-4 bg-blue-100 rounded">
<h2 className="text-xl font-bold">Welcome</h2>
<p>Content without animations</p>
</div>
</div>
)
}
return (
<div className="space-y-4">
<FadeIn>
<div className="p-4 bg-blue-100 rounded">
<h2 className="text-xl font-bold">Welcome</h2>
<p>Content with animations</p>
</div>
</FadeIn>
</div>
)
}
Optimize for Low-Power Devices
Detect and adapt to low-power devices.
import { FadeIn, SlideUp } from '@foundrykit/animation'
import { useMediaQuery } from '@foundrykit/hooks'
function LowPowerOptimized() {
const isLowPower = useMediaQuery('(prefers-reduced-motion: reduce)')
const isMobile = useMediaQuery('(max-width: 768px)')
// Use simpler animations on low-power devices
const animationProps = {
duration: isLowPower || isMobile ? 0.3 : 0.6,
easing: isLowPower ? 'linear' : 'ease-out'
}
return (
<div className="space-y-4">
<FadeIn {...animationProps}>
<div className="p-4 bg-green-100 rounded">
Optimized for your device
</div>
</FadeIn>
<SlideUp {...animationProps}>
<div className="p-4 bg-blue-100 rounded">
Smooth performance
</div>
</SlideUp>
</div>
)
}
Performance Monitoring
Track Animation Performance
Monitor animation performance in development.
import { FadeIn } from '@foundrykit/animation'
import { useEffect, useRef } from 'react'
function PerformanceTrackedAnimation() {
const startTimeRef = useRef(performance.now())
const animationRef = useRef(null)
useEffect(() => {
const endTime = performance.now()
const duration = endTime - startTimeRef.current
if (process.env.NODE_ENV === 'development') {
console.log(`Animation completed in ${duration.toFixed(2)}ms`)
// Warn if animation takes too long
if (duration > 100) {
console.warn('Animation may be causing performance issues')
}
}
}, [])
return (
<FadeIn ref={animationRef}>
<div className="p-4 bg-purple-100 rounded">
Performance tracked animation
</div>
</FadeIn>
)
}
Monitor Frame Rate
Check for animation frame drops.
import { useEffect, useRef } from 'react'
function useFrameRateMonitor() {
const frameCountRef = useRef(0)
const lastTimeRef = useRef(performance.now())
useEffect(() => {
const checkFrameRate = () => {
frameCountRef.current++
const currentTime = performance.now()
if (currentTime - lastTimeRef.current >= 1000) {
const fps = Math.round((frameCountRef.current * 1000) / (currentTime - lastTimeRef.current))
if (process.env.NODE_ENV === 'development') {
console.log(`Current FPS: ${fps}`)
if (fps < 30) {
console.warn('Low frame rate detected. Consider reducing animations.')
}
}
frameCountRef.current = 0
lastTimeRef.current = currentTime
}
requestAnimationFrame(checkFrameRate)
}
const animationId = requestAnimationFrame(checkFrameRate)
return () => cancelAnimationFrame(animationId)
}, [])
}
function MonitoredAnimations() {
useFrameRateMonitor()
return (
<div className="space-y-4">
<FadeIn>
<div className="p-4 bg-red-100 rounded">Monitored animation</div>
</FadeIn>
</div>
)
}
Optimization Techniques
Use CSS Containment
Improve performance with CSS containment.
import { FadeIn, Stagger } from '@foundrykit/animation'
function ContainedAnimations() {
return (
<div className="contain-layout contain-paint">
<FadeIn>
<div className="p-4 bg-blue-100 rounded">
Contained animation
</div>
</FadeIn>
<Stagger>
<div className="space-y-2">
{[1, 2, 3].map(i => (
<div key={i} className="p-2 bg-gray-100 rounded">
Item {i}
</div>
))}
</div>
</Stagger>
</div>
)
}
Optimize for GPU
Use GPU-accelerated properties for better performance.
import { FadeIn, SlideUp } from '@foundrykit/animation'
function GPUOptimized() {
return (
<div className="space-y-4">
{/* These animations use GPU-accelerated properties */}
<FadeIn>
<div className="p-4 bg-green-100 rounded will-change-opacity">
GPU-accelerated fade
</div>
</FadeIn>
<SlideUp>
<div className="p-4 bg-blue-100 rounded will-change-transform">
GPU-accelerated slide
</div>
</SlideUp>
</div>
)
}
Lazy Load Animations
Load animations only when needed.
import { lazy, Suspense } from 'react'
import { FadeIn } from '@foundrykit/animation'
const LazyAnimatedComponent = lazy(() =>
import('./LazyAnimatedComponent').then(m => ({ default: m.LazyAnimatedComponent }))
)
function LazyLoadedAnimations() {
const [showLazy, setShowLazy] = useState(false)
return (
<div className="space-y-4">
<FadeIn>
<div className="p-4 bg-yellow-100 rounded">
Immediate animation
</div>
</FadeIn>
<button onClick={() => setShowLazy(true)}>
Load Lazy Animation
</button>
{showLazy && (
<Suspense fallback={<div className="p-4 bg-gray-100 rounded">Loading...</div>}>
<LazyAnimatedComponent />
</Suspense>
)}
</div>
)
}
Performance Checklist
Before Production
- Test animations on low-end devices
- Verify reduced motion preferences are respected
- Check for memory leaks in long-running animations
- Monitor frame rate during complex animations
- Optimize animation timing for smooth performance
- Use transform-based animations instead of layout-triggering ones
- Limit concurrent animations to prevent performance issues
- Implement proper cleanup for unmounted components
Performance Metrics
- Target FPS: 60 FPS for smooth animations
- Animation Duration: 200-600ms for most interactions
- Stagger Delay: 50-150ms between staggered items
- Memory Usage: Monitor for leaks in long-running animations
- Layout Thrashing: Avoid multiple layout recalculations
Next Steps
- Review best practices for effective usage
- Learn about animation utilities for advanced patterns
- Explore the animation components for detailed usage examples