A lightweight JavaScript scroll animation library using the Intersection Observer API. ScrollCue.js animates elements when they enter the viewport, with configurable animations, delays, and durations. Now with buttery-smooth advanced animations while remaining dependency-free!
- Dependency-free (no jQuery required)
- Lightweight
- Uses modern Intersection Observer API
- Multiple animation types with buttery-smooth transitions
- Physics-based animations for natural movement
- Advanced easing functions for natural motion
- Staggered animations for groups of elements
- Timeline sequencing for complex animations
- Scroll-linked animations and progress tracking
- Transform origin controls and 3D perspective
- Works automatically when included (like particles.js)
- Can be used directly from CDN - no downloads needed
- One-line implementation available (JS + CSS together)
The simplest way to use ScrollCue.js is with the all-in-one version that includes both JS and CSS in a single file:
<!-- From npm -->
<script src="https://cdn.jsdelivr.net/npm/scrollcue.js@latest/scrollcue.all-in-one.js"></script>
<!-- Or -->
<script src="https://unpkg.com/scrollcue.js@latest/scrollcue.all-in-one.js"></script>Or download the files from this repository and include them in your project:
<script src="path/to/scrollcue.all-in-one.js"></script>That's it! No initialization code needed. ScrollCue.js automatically detects elements with the scrollcue class and sets up animations when the page loads.
- Add the
scrollcueclass to any element you want to animate when scrolled into view. - Add a
data-cueattribute to specify the animation type. - Optionally add
data-delayanddata-durationattributes for timing control.
<div class="scrollcue" data-cue="fade-in">
This element will fade in when scrolled into view.
</div>
<div class="scrollcue" data-cue="slide-up" data-delay="200" data-duration="1000">
This element will slide up with a 200ms delay and 1000ms duration.
</div>For advanced configuration and customization options, check out the instructions file.
fade-in: Simple fade-in effectslide-up: Slides up from below with physics-based momentumslide-down: Slides down from above with physics-based momentumslide-left: Slides in from the right with smooth decelerationslide-right: Slides in from the left with smooth decelerationzoom-in: Scales up from smaller size with slight overshootzoom-out: Scales down from larger size with spring-like motionrotate-in: Rotates and fades in with natural dampingflip-in: Flips in with realistic 3D physicsbounce-in: Bounces in with enhanced elastic effectspring: Spring-physics animation with natural oscillationelastic-in: Elastic animation with spring-like oscillationflip-3d: Advanced 3D flip with perspective and rotation
wave: Gentle wave-like motion with improved physicsfloat: Smooth floating animation with subtle rotationwind: Wind sweeping effect with natural movementripple: Water ripple effect with radial expansionboat-rock: Realistic boat rocking motionstorm: Dynamic storm-like shakingbreaking-wave: Natural wave breaking motiontyping: Type text character by character with optional blinking cursorshake: Quick shake animation with physics-based dampingflicker: Light flickering effect with brightnessstagger: Animate child elements in sequence with configurable delays
morph: Dynamic morphing transform animationmorph-circle: Morph with circular transformationmorph-square: Morph with square transformationskew: Dynamic skew transformationskew-left: Skew transformation to the leftskew-right: Skew transformation to the rightskew-dynamic: Dynamic skew with variable anglesstretch: Stretch animation effectstretch-h: Horizontal stretch animationstretch-both: Stretch in both directionsstretch-dynamic: Dynamic stretch with variable scaling
fade-split: Split text animation effectzoom-path: Advanced zoom with path-based motionparallax: [BETA] Parallax scrolling effect - may require fixescombo-parallax: [BETA] Combined parallax effects - may require fixes
Note: Beta animations are experimental features that may have known issues or require additional refinement. Use with caution in production environments.
Basic animations:
<div class="scrollcue" data-cue="fade-in">
This element will fade in when scrolled into view.
</div>
<div class="scrollcue" data-cue="slide-up" data-delay="200" data-duration="1000">
This element will slide up with a 200ms delay and 1000ms duration.
</div>Special effects:
<!-- Ocean-themed effects -->
<div class="scrollcue" data-cue="wave">
Wave motion effect
</div>
<div class="scrollcue" data-cue="boat-rock">
β΅ Boat rocking animation
</div>
<div class="scrollcue" data-cue="ripple">
π§ Ripple effect
</div>
<!-- Stagger animation -->
<div class="scrollcue" data-cue="stagger" data-stagger="100" data-child-cue="fade-in">
<div>First item</div>
<div>Second item</div>
<div>Third item</div>
</div>Typing animation:
<!-- Basic typing (100ms per character, no cursor) -->
<div class="scrollcue" data-cue="typing">
This text will be typed out character by character!
</div>
<!-- Fast typing (50ms per character) -->
<div class="scrollcue" data-cue="typing" data-typing-speed="50">
This types much faster!
</div>
<!-- Slow typing (200ms per character) -->
<div class="scrollcue" data-cue="typing" data-typing-speed="200">
This types slower...
</div>
<!-- With blinking cursor -->
<div class="scrollcue" data-cue="typing" data-cursor="true">
This types with a realistic blinking cursor!
</div>
<!-- Custom speed with cursor -->
<div class="scrollcue" data-cue="typing" data-typing-speed="75" data-cursor="true">
Perfect speed with cursor effect!
</div>Typing Animation Variables:
data-typing-speed: Milliseconds between each character (default: 100)data-cursor: Set to "true" to show blinking cursor (default: no cursor)
Stagger Animation Variables:
data-stagger: Milliseconds delay between each child element animation (default: 100)data-child-cue: Animation type for child elements (default: "fade-in")
Transform animations:
<!-- Morphing effects -->
<div class="scrollcue" data-cue="morph">
Dynamic morph transformation
</div>
<div class="scrollcue" data-cue="morph-circle">
π΅ Circular morph effect
</div>
<!-- Skew transformations -->
<div class="scrollcue" data-cue="skew-left">
βοΈ Left skew animation
</div>
<div class="scrollcue" data-cue="skew-dynamic" data-duration="1500">
π Dynamic skew effect
</div>
<!-- Stretch effects -->
<div class="scrollcue" data-cue="stretch-h">
βοΈ Horizontal stretch
</div>
<div class="scrollcue" data-cue="stretch-both">
π Stretch in both directions
</div>Beta animations (use with caution):
<!-- Advanced path animation -->
<div class="scrollcue" data-cue="zoom-path">
π€οΈ Zoom with path motion
</div>
<!-- Beta features - may require fixes -->
<div class="scrollcue" data-cue="fade-split">
β οΈ Split fade animation (Beta)
</div>
<div class="scrollcue" data-cue="parallax" data-duration="2000">
β οΈ Parallax effect (Beta)
</div>
<div class="scrollcue" data-cue="combo-parallax">
β οΈ Combined parallax (Beta)
</div>ScrollCue.js initializes automatically when included - no manual initialization required. However, you can control it with JavaScript if needed:
// Access the global instance
window.scrollCue
// Manual refresh to detect new elements
scrollCue.refresh();
// Destroy instance
scrollCue.destroy();
// Create a new instance with custom options
const myScrollCue = new ScrollCue({
rootMargin: '0px',
threshold: 0.2,
duration: 800,
delay: 0,
easing: 'cubic-bezier(0.25, 0.1, 0.25, 1.0)',
once: true,
useRAF: true, // Use requestAnimationFrame for smoother animations
stagger: 150 // Default stagger delay for child elements
});
myScrollCue.init();
// Advanced Timeline functionality
const timeline = scrollCue.timeline()
.add('#first-element', {cue: 'fade-in', delay: 0})
.add('#second-element', {cue: 'slide-up', position: '+=200'})
.add('#third-element', {cue: 'zoom-in', position: '<'});
timeline.play();
// Create staggered animations
scrollCue.sequence('#container')
.add('.item', {cue: 'fade-in', stagger: 100})
.play();
// Register custom easing functions
scrollCue.registerEasing('customBounce', 'cubic-bezier(0.175, 0.885, 0.32, 1.275)');
// Create scroll-linked animations
scrollCue.scrollTween('.parallax-element', {
start: 'top bottom', // When element top reaches bottom of viewport
end: 'bottom top', // When element bottom reaches top of viewport
properties: {
y: {from: 0, to: -100, unit: 'px'},
opacity: {from: 0, to: 1},
scale: {from: 0.8, to: 1}
}
});
// Add custom animations
scrollCue.addAnimation('custom-animation', {
initial: 'transform: rotate(45deg); opacity: 0;',
visible: 'transform: rotate(0); opacity: 1;',
keyframes: `
0% { transform: rotate(45deg); opacity: 0; }
100% { transform: rotate(0); opacity: 1; }
`
});| Option | Type | Default | Description |
|---|---|---|---|
| rootMargin | String | '0px' | Margin around the root. See Intersection Observer API. |
| threshold | Number | 0.2 | Percentage of element visibility needed to trigger animation. |
| duration | Number | 800 | Default animation duration in milliseconds. |
| delay | Number | 0 | Default delay before animation starts in milliseconds. |
| easing | String | 'cubic-bezier(0.25, 0.1, 0.25, 1.0)' | CSS timing function for animations. |
| once | Boolean | true | Whether to animate elements only once or every time they enter the viewport. |
| useRAF | Boolean | true | Whether to use requestAnimationFrame for smoother animations. |
| stagger | Number | 0 | Default stagger delay for child elements in milliseconds. |
| ease | String | 'cubic-bezier(0.25, 0.1, 0.25, 1.0)' | Alias for easing (compatible naming). |
ScrollCue.js works in all modern browsers that support the Intersection Observer API (Chrome, Firefox, Safari, Edge). A fallback is provided for older browsers, which will simply display all elements without animation.
MIT License
If you're interested in contributing to ScrollCue.js, please check out the CONTRIBUTING.md file for guidelines.
Important: Don't edit the all-in-one files directly. Make changes to the separate scrollcue.js and scrollcue.css files, then generate the combined version as described in the contributing guide.
Star this repository if you found it helpful! It'd help me a lot.