css based solution

css-scroll-snap

native, accessible, bolt on

cons: no custom animations.. is that true, can you tie into it maybe?


gpt-co-created

Scroll Hijacking Options for Slide Deck Experience

What is Scroll Hijacking?

Scroll hijacking (also called “scroll locking” or “scroll control”) is a technique where you intercept the browser’s default scroll behavior and replace it with custom animations or transitions. Instead of smooth scrolling, you get:

  • Snap-to-slide behavior - Scroll “locks” onto each full-page slide
  • Animation between slides - Transitions, fades, or other effects
  • Partial scroll reveals - User scrolls partway, then animation completes the transition
  • Programmatic control - JavaScript controls when slides change, not just scroll position

Example: User scrolls down 20%, JavaScript detects this, then animates a smooth transition to the next slide and “locks” there.


Option 1: CSS Scroll Snap (Native, No JavaScript)

What it is: Native CSS feature that snaps scrolling to specific points.

Implementation:

.slide-container {
    
    
scroll-snap-type: y mandatory;
    
    
overflow-y: scroll;
    
    
height: 100vh;
    
    
}
    
    
      
    
.slide {
    
    
scroll-snap-align: start;
    
    
height: 100vh;
    
    
}

Pros:

  • Native browser support - No JavaScript needed
  • Performance - Hardware accelerated, smooth
  • Accessible - Works with keyboard navigation, screen readers
  • Simple - Just CSS, easy to implement
  • Mobile-friendly - Works great on touch devices

Cons:

  • Limited control - Can’t add custom animations between slides
  • No partial scroll - Snaps immediately, no “scroll 20% then animate” behavior
  • No scroll locking - User can still scroll past if they scroll fast
  • Basic transitions - Only snap, no fade/slide animations

Best for: Simple slide decks where you just want snap-to-slide behavior.


Option 2: fullPage.js Library

What it is: Popular JavaScript library specifically for full-page scrolling websites.

Website: https://github.com/alvarotrigo/fullpage.js

Installation:

npm install fullpage.js

Usage:

new fullpage('#fullpage', {
    
    
sectionsColor: ['#f8f8f7', '#c6c6b9', '#272726'],
    
    
navigation: true,
    
    
scrollOverflow: true,
    
    
onLeave: (origin, destination) => {
    
    
// Custom animations here
    
    
}
    
    
});

Pros:

  • Feature-rich - Navigation dots, keyboard controls, hash URLs
  • Well-documented - Extensive docs and examples
  • Active maintenance - Regularly updated
  • Responsive - Works on mobile/tablet/desktop
  • Animations - Built-in transition effects
  • Community - Large user base, lots of examples

Cons:

  • Heavy dependency - Adds ~50KB+ to bundle
  • Opinionated - May conflict with your design system
  • jQuery dependency (older versions) - Newer versions are vanilla JS
  • Less flexible - Harder to customize deeply
  • Overkill - Might be more than you need

Best for: When you want a complete solution with minimal custom code.


Option 3: Locomotive Scroll

What it is: Modern, lightweight scroll library with smooth scrolling and scroll-triggered animations.

Website: https://github.com/locomotivemtl/locomotive-scroll

Installation:

npm install locomotive-scroll

Usage:

import LocomotiveScroll from 'locomotive-scroll';
    
    
      
    
const scroll = new LocomotiveScroll({
    
    
el: document.querySelector('[data-scroll-container]'),
    
    
smooth: true,
    
    
scrollbarContainer: document.querySelector('[data-scroll-container]'),
    
    
});

Pros:

  • Smooth scrolling - Buttery smooth, hardware accelerated
  • Lightweight - Smaller than fullPage.js
  • Modern - Built for modern browsers
  • Flexible - Easy to customize
  • Scroll-triggered animations - Can trigger animations on scroll
  • Good performance - Optimized for 60fps

Cons:

  • Not slide-specific - More general-purpose, not built for slide decks
  • Requires setup - Need to configure scroll containers
  • Less slide features - No built-in navigation dots, hash URLs
  • Custom work needed - You build the slide locking logic

Best for: When you want smooth scrolling with custom slide behavior.


Option 4: Custom JavaScript (Vanilla or Framework)

What it is: Build your own scroll hijacking system from scratch.

Implementation approach:

let currentSlide = 0;
    
    
const slides = document.querySelectorAll('.slide');
    
    
const isScrolling = false;
    
    
      
    
window.addEventListener('wheel', (e) => {
    
    
e.preventDefault();
    
    
    
if (isScrolling) return;
    
    
    
if (e.deltaY > 0 && currentSlide < slides.length - 1) {
    
    
// Scroll down - go to next slide
    
    
goToSlide(currentSlide + 1);
    
    
} else if (e.deltaY < 0 && currentSlide > 0) {
    
    
// Scroll up - go to previous slide
    
    
goToSlide(currentSlide - 1);
    
    
}
    
    
});
    
    
      
    
function goToSlide(index) {
    
    
isScrolling = true;
    
    
currentSlide = index;
    
    
    
// Animate to slide
    
    
slides[index].scrollIntoView({ behavior: 'smooth' });
    
    
    
// Lock scroll during animation
    
    
setTimeout(() => {
    
    
isScrolling = false;
    
    
}, 1000);
    
    
}

Pros:

  • Full control - Complete control over behavior
  • No dependencies - Zero bundle size impact
  • Custom animations - Any animation library (GSAP, Framer Motion, etc.)
  • Lightweight - Only what you need
  • Framework-agnostic - Works with any setup

Cons:

  • Time-consuming - Significant development time
  • Edge cases - Need to handle touch, keyboard, accessibility
  • Maintenance - You own all the code
  • Testing - Need to test across devices/browsers
  • Complexity - Can get complicated quickly

Best for: When you need specific behavior that libraries don’t provide, or want zero dependencies.


Option 5: GSAP ScrollTrigger + ScrollSmoother

What it is: Professional animation library with powerful scroll control plugins.

Website: https://greensock.com/scrolltrigger/ | https://greensock.com/scrollsmoother/

Installation:

npm install gsap

Usage:

import { gsap } from 'gsap';
    
    
import { ScrollTrigger } from 'gsap/ScrollTrigger';
    
    
import { ScrollSmoother } from 'gsap/ScrollSmoother';
    
    
      
    
gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
    
    
      
    
ScrollSmoother.create({
    
    
wrapper: '#smooth-wrapper',
    
    
content: '#smooth-content',
    
    
smooth: 1.5,
    
    
effects: true,
    
    
});
    
    
      
    
// Custom slide locking with ScrollTrigger
    
    
slides.forEach((slide, index) => {
    
    
ScrollTrigger.create({
    
    
trigger: slide,
    
    
start: 'top top',
    
    
end: 'bottom top',
    
    
pin: true,
    
    
pinSpacing: false,
    
    
});
    
    
});

Pros:

  • Powerful animations - Industry-standard animation library
  • Smooth scrolling - ScrollSmoother for buttery smoothness
  • Scroll-triggered - Perfect for scroll-based animations
  • Professional - Used by major brands
  • Flexible - Can build any scroll behavior
  • Performance - Highly optimized

Cons:

  • Cost - ScrollSmoother requires paid license for commercial use
  • Learning curve - GSAP has its own API to learn
  • Bundle size - GSAP + plugins can be ~50KB+
  • Overkill - Might be more than needed for simple slide decks

Best for: When you need professional-grade animations and have budget for licensing.


Recommendation for Your Project

Given your requirements:

  • ✅ Slide deck presentation style
  • ✅ Partial scroll then animation lock
  • ✅ Designer-led project (needs to be maintainable)
  • ✅ Astro (static site, minimal JS)

I’d recommend: Option 1 (CSS Scroll Snap) + Option 4 (Custom JS for locking)

Why:

  1. Start with CSS Scroll Snap - Get basic snap behavior working immediately
  2. Add minimal custom JS - Just add scroll locking logic (prevent scroll during transitions)
  3. Add animations - Use CSS transitions or a lightweight animation library

This gives you:

  • ✅ Native performance (CSS scroll snap)
  • ✅ Custom control (JS for locking)
  • ✅ Minimal dependencies
  • ✅ Easy to maintain

Alternative: If you want a complete solution quickly, Option 2 (fullPage.js) is the fastest path, but adds a dependency.


Next Steps

  1. Start simple: Implement CSS scroll snap first
  2. Test behavior: See if native snap is enough
  3. Add locking: If you need partial scroll + animation, add custom JS
  4. Consider library: If custom gets complex, evaluate fullPage.js