View Animations
View animations automatically trigger when elements enter the viewport. The view prop uses Intersection Observer to detect when elements become visible, perfect for scroll-triggered reveals and progressive disclosure.
Basic Usage
The view prop accepts an animation descriptor that runs when the element enters the viewport:
import { animate, withTiming, withSpring } from 'react-ui-animate';
function ScrollReveal() {
return (
<animate.div
view={{
opacity: withTiming(1),
translateY: withSpring(0),
}}
style={{
opacity: 0,
translateY: 50,
width: 100,
height: 100,
background: 'teal',
}}
>
Scroll to see me
</animate.div>
);
}
View Options
Control when and how the animation triggers with viewOptions:
<animate.div
view={{
opacity: withTiming(1),
}}
viewOptions={{
threshold: 0.3, // Trigger when 30% visible
once: true, // Only animate once
}}
style={{
opacity: 0,
}}
>
Content
</animate.div>
Available Options
| Option | Type | Default | Description |
|---|---|---|---|
threshold | number | 0 | Percentage of element that must be visible (0-1) |
once | boolean | false | Whether to animate only once |
rootMargin | string | '0px' | Margin around root (e.g., '100px' to trigger earlier) |
Real-World Examples
Example 1: Feature Card
function FeatureCard({ title, description }) {
return (
<animate.div
view={{
opacity: withTiming(1, { duration: 600 }),
translateY: withSpring(0),
}}
viewOptions={{
threshold: 0.3,
once: true,
}}
style={{
opacity: 0,
translateY: 50,
padding: 20,
background: 'white',
borderRadius: 8,
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
}}
>
<h3>{title}</h3>
<p>{description}</p>
</animate.div>
);
}
Example 2: Staggered List
function StaggeredList({ items }) {
return (
<div>
{items.map((item, index) => (
<animate.div
key={item.id}
view={{
opacity: withTiming(1, { duration: 400 }),
translateX: withSpring(0),
}}
viewOptions={{
threshold: 0.2,
once: true,
}}
style={{
opacity: 0,
translateX: -50,
padding: 20,
marginBottom: 10,
background: 'white',
borderRadius: 4,
}}
>
{item.name}
</animate.div>
))}
</div>
);
}
Example 3: Progress Indicator
function ProgressBar() {
return (
<animate.div
view={{
width: withTiming('100%', { duration: 1000 }),
}}
viewOptions={{
threshold: 0.5,
once: true,
}}
style={{
width: '0%',
height: 4,
background: 'teal',
borderRadius: 2,
}}
/>
);
}
Combining with Other Animations
You can combine view with other animation props:
<animate.div
animate={{
opacity: withSpring(1),
}}
view={{
translateY: withSpring(0),
}}
hover={{
scale: withSpring(1.05),
}}
style={{
opacity: 0,
translateY: 50,
}}
>
Multi-animated content
</animate.div>
Performance Tips
- Use
once: true- Prevents re-animating on scroll - Set appropriate threshold - Don't trigger too early or too late
- Use transforms -
translateY,translateXare GPU-accelerated - Limit animated properties - Fewer properties = better performance
Best Practices
✅ Do
- Use
once: truefor most scroll reveals - Set appropriate
thresholdvalues (0.2-0.5 is usually good) - Use
withTimingfor predictable scroll animations - Test on different screen sizes
❌ Don't
- Don't animate too many elements at once
- Don't use
viewfor elements always in viewport - Don't forget to set initial styles (opacity: 0, etc.)
- Don't make animations too slow (users scroll quickly)
Next Steps
- Learn about Hover Animations for mouse interactions
- Explore Press Animations for click feedback
- Check out Focus Animations for accessibility