Scroll-Jacking and Vestibular Risk
Part of Vestibular-Safe Motion Patterns in Accessible Motion Architecture.
The problem
A product story page takes over scrolling: each wheel gesture advances to the next full-screen section with an animated transition, regardless of how far the user scrolled. Keyboard Page Down jumps two sections. Find-in-page highlights text that is never shown. Users describe it as “fighting the page”, and several report motion sickness.
The same page could tell the same story with native scrolling and scroll-driven animation, and nearly all the discomfort would go with the hijacking.
Root cause analysis: control and prediction
Two properties make ordinary scrolling comfortable. The user controls the amount of movement, and they can predict it — a small gesture moves the page a little.
Scroll-jacking removes both. A wheel handler that calls preventDefault() and animates to a fixed destination means a small gesture produces a large, fixed movement. The eyes see substantial motion the user did not command, which is the same mismatch behind other vestibular triggers described in replacing parallax with accessible alternatives.
It also breaks mechanics users rely on. Momentum scrolling, keyboard paging, Home and End, scrollbar dragging, find-in-page and screen reader “read from here” all assume the document scrolls normally.
Scroll-driven animation is different. An animation whose progress is tied to the scroll position moves because the user moved, in proportion to their gesture, and stops when they stop. The relationship is under their control, which is why scroll-driven animation patterns are broadly acceptable where scroll-jacking is not.
Scroll snapping sits in between. scroll-snap-type: proximity nudges to a nearby point and is usually unobtrusive. mandatory forces every scroll to land on a snap point, which on a long page behaves much like hijacking and can trap users between sections.
Displacement still matters. Even with native scrolling, a scroll-linked effect that moves a full-screen layer a long way as the user scrolls creates large-area motion. Proportional is not automatically safe; it must also be modest.
Step-by-step resolution
Production code pattern
/* Native scrolling, with gentle alignment. */
.story {
scroll-snap-type: y proximity; /* not mandatory */
scroll-padding-block-start: var(--header-h);
}
.story__section {
scroll-snap-align: start;
min-block-size: 100svh;
}
/* Section effects follow the user's scroll, with small displacement. */
.story__content {
animation: section-reveal linear both;
animation-timeline: view();
animation-range: entry 10% entry 70%;
}
@keyframes section-reveal {
from { opacity: 0; translate: 0 24px; } /* 24px, not a full screen */
}
@media (prefers-reduced-motion: reduce) {
.story { scroll-snap-type: none; } /* no snapping */
.story__content { animation: none; }
}
// What NOT to do, kept as a comment for reviewers:
// window.addEventListener('wheel', (e) => { e.preventDefault(); goToSection(next); }, { passive: false });
// If a "next section" control is wanted, make it an explicit button.
document.querySelectorAll('[data-next-section]').forEach((button) => {
button.addEventListener('click', () => {
const target = document.getElementById(button.dataset.nextSection);
target.scrollIntoView({
behavior: matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth',
block: 'start',
});
target.focus({ preventScroll: true });
});
});
Rendering Impact: composite. Scroll-driven animations on
opacityandtranslateare evaluated with scrolling rather than by script, so removing the hijacking also removes a wheel handler from the main thread.
Offering an explicit “next section” button gives users who want section-by-section navigation a way to get it, without imposing it on everyone. It is also reachable by keyboard, unlike a hijacked wheel gesture.
Horizontal sections and sticky sequences
The horizontal scroll section pattern — a tall runway with a sticky stage whose content moves sideways — keeps native scrolling, so it avoids the worst problems. It still creates large-area lateral motion driven by vertical input, which is a mismatch of a different kind: the user scrolls down and the world moves sideways.
Keep such sections short, keep the horizontal movement roughly proportional to the vertical scroll, and provide the reduced-motion alternative of a plain horizontal scroller. The same applies to long sticky “scrollytelling” sequences: they are acceptable when each scroll step produces a modest, proportional change, and uncomfortable when a small gesture triggers a large scene change.
Verification checklist
Constraints and trade-offs
- Native scrolling gives less precise control over pacing than a hijacked sequence.
- Proximity snapping aligns less reliably than mandatory snapping.
- Scroll-driven animations are not supported everywhere; the static fallback must be complete.
- Long sticky sequences still require careful displacement limits.
- Some design concepts depend on fixed section pacing; they may need rethinking rather than adjusting.
Frequently asked questions
What is scroll-jacking?
Intercepting scroll input and replacing it with scripted movement, so the page moves by an amount the user did not choose.
Are scroll-driven animations the same as scroll-jacking?
No. They tie an animation’s progress to the scroll position the user controls, without changing how much the page scrolls.
Is scroll snapping acceptable?
Proximity snapping usually is. Mandatory snapping on long pages behaves like hijacking and can trap users between sections.
How much movement is safe in a scroll-linked effect?
Keep displacement modest — tens of pixels rather than full screens — and favour opacity changes for large surfaces.
Related
- Vestibular-Safe Motion Patterns — the parent topic
- Replacing Parallax with Accessible Alternatives — the related depth-cue problem
- Smooth Scrolling Under Reduced Motion — programmatic scrolling and the preference