Scroll-Driven Animations
Overview
Scroll-driven animations in the Phenix Animation System are animations that progress based on the user's scroll position. Unlike standard viewport animations that play once when an element enters the viewport, scroll-driven animations continuously update as the user scrolls, creating a more interactive and immersive experience.
Basic Usage
To create scroll-driven animations, use the animations
method with the scrollDriven
option:
animations(options?: {
animation?: string; // Animation name
duration?: number; // Animation duration in milliseconds
delay?: number; // Animation delay in milliseconds
scrollDriven?: boolean; // Enable scroll-driven animations
drivenEnd?: number | string; // End point for scroll-driven animations
flow?: string; // Scroll direction ('start', 'end', 'both')
}): this
Key Parameters for Scroll-Driven Animations
scrollDriven
: Set totrue
to enable scroll-driven animationsdrivenEnd
: Defines when the animation should complete:"top"
: Animation completes when element reaches viewport top"center"
: Animation completes when element reaches viewport center"bottom"
: Animation completes when element reaches viewport bottom- A percentage (e.g.,
"50"
for 50% of viewport height)
HTML Attributes
The method also supports HTML data attributes for inline configuration:
data-animation
: Name of the animation to applydata-scrollDriven
: If "true", enables scroll-driven animationsdata-drivenEnd
: End point for scroll-driven animations
Examples
Basic Usage
// Initialize scroll-driven animations
Phenix('.parallax-element').animations({
animation: 'fadeIn',
scrollDriven: true,
drivenEnd: 'center'
});
HTML Implementation
<!-- Basic scroll-driven animation -->
<div data-animation="fadeIn"
data-scrollDriven="true"
data-drivenEnd="center">
This animation progresses as the user scrolls
</div>
<!-- Scroll-driven animation with custom end point -->
<div data-animation="fadeInUp"
data-scrollDriven="true"
data-drivenEnd="top">
This animation completes when the element reaches the top of the viewport
</div>
How Scroll-Driven Animations Work
Scroll-driven animations calculate the element's position relative to the viewport and adjust the animation's progress accordingly:
- When the element first enters the viewport, the animation is at 0% progress
- As the user scrolls, the animation progresses based on the element's position
- When the element reaches the defined end point (
drivenEnd
), the animation is at 100% progress
This creates a smooth, continuous animation that feels connected to the user's scrolling action.
Practical Examples
Parallax Hero Section
<section class="hero-section">
<div class="background-layer"
data-animation="fadeIn"
data-scrollDriven="true"
data-drivenEnd="bottom">
</div>
<div class="content-container">
<h1 data-animation="fadeInUp" data-delay="300">Welcome to Our Site</h1>
<p data-animation="fadeInUp" data-delay="600">Discover our amazing products and services</p>
<a href="#learn-more" class="btn" data-animation="fadeInUp" data-delay="900">
Learn More
</a>
</div>
</section>
// Initialize all animations
Phenix('[data-animation]').animations();
Scroll-Driven Progress Bar
<div class="progress-container">
<div class="progress-bar"
data-animation="slideInEnd"
data-scrollDriven="true"
data-drivenEnd="bottom">
</div>
<div class="content-section">
<h2>Our Services</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
<!-- More content here -->
</div>
</div>
// Initialize the progress bar
Phenix('.progress-bar').animations({
scrollDriven: true,
drivenEnd: 'bottom'
});
Scroll-Driven Image Reveal
<div class="image-reveal-container">
<div class="image-wrapper">
<img src="image.jpg" alt="Description"
data-animation="fadeIn"
data-scrollDriven="true"
data-drivenEnd="center">
</div>
<div class="overlay"
data-animation="slideOutEnd"
data-scrollDriven="true"
data-drivenEnd="center">
</div>
</div>
// Initialize the image reveal animations
Phenix('.image-reveal-container [data-animation]').animations();
Scroll-Driven Text Transformation
<div class="text-transform-section">
<h2 class="transform-text"
data-animation="fadeIn"
data-scrollDriven="true"
data-drivenEnd="center">
Transform as you scroll
</h2>
</div>
// Initialize the text transformation
Phenix('.transform-text').animations({
scrollDriven: true,
drivenEnd: 'center'
});
// Add custom scroll event to modify additional properties
document.addEventListener('scroll', function() {
const element = document.querySelector('.transform-text');
const rect = element.getBoundingClientRect();
const windowHeight = window.innerHeight;
// Calculate progress (0 to 1)
const progress = Math.max(0, Math.min(1,
1 - (rect.top / (windowHeight - rect.height))));
// Apply additional transformations based on scroll progress
element.style.transform = `scale(${1 + (progress * 0.2)})`;
element.style.letterSpacing = `${progress * 5}px`;
});
Combining with Standard Animations
You can combine scroll-driven animations with standard viewport animations for complex effects:
<section class="combined-section">
<!-- Standard viewport animation -->
<h2 data-animation="fadeInDown">Our Products</h2>
<!-- Scroll-driven background effect -->
<div class="background-effect"
data-animation="fadeIn"
data-scrollDriven="true"
data-drivenEnd="bottom">
</div>
<!-- Product items with standard animations -->
<div class="products-container" data-lazy-group="true" data-stagger="150">
<div class="product-card" data-animation="fadeInUp">Product 1</div>
<div class="product-card" data-animation="fadeInUp">Product 2</div>
<div class="product-card" data-animation="fadeInUp">Product 3</div>
</div>
</section>
Performance Optimization
Limit the Number of Scroll-Driven Animations: These animations can be more resource-intensive than standard animations, so use them sparingly.
Use
requestAnimationFrame
: For custom scroll effects, always userequestAnimationFrame
to ensure smooth performance:
let ticking = false;
document.addEventListener('scroll', function() {
if (!ticking) {
window.requestAnimationFrame(function() {
// Your scroll-driven animation code here
ticking = false;
});
ticking = true;
}
});
Optimize Animation Properties: Stick to properties that are cheap to animate:
opacity
andtransform
are most efficient- Avoid animating
width
,height
, ortop
/left
properties
Consider Mobile Performance: Mobile devices may struggle with complex scroll-driven animations. Test thoroughly and consider providing simplified versions for mobile users.
Debugging Scroll-Driven Animations
If your scroll-driven animations aren't working as expected, check these common issues:
Element Visibility: Ensure the element is tall enough or the viewport is small enough for the scroll-driven effect to be noticeable.
Drivent End Point: Make sure the
drivenEnd
value is appropriate for your layout and the size of your element.Scroll Container: By default, animations track scrolling relative to the viewport. If you're using a custom scroll container, you'll need additional JavaScript to track that container's scroll position.
Browser Compatibility
Scroll-driven animations use the Intersection Observer API and standard scroll events, which are supported in all modern browsers. For older browsers, consider using a polyfill for Intersection Observer.