ScrollToPlugin
ScrollToPlugin is a GSAP plugin that animates scroll position, so you can smooth-scroll the window or any scrollable element to a pixel value or a target element with an ease and duration you control. It's the tool behind smooth anchor navigation, scroll-to-top buttons, and jump-to-section links that glide instead of snapping.
Updated July 1, 2026
How ScrollToPlugin works
You tween the scroll position of a target the same way you tween any other property. Instead of animating x or opacity on an element, you animate the scrollTo property on window (or on a scrollable container). GSAP reads and writes the scroll position each frame, so the whole thing eases like a normal tween.
The scrollTo object takes y (or x) as a number, a selector, or an element. Pass "max" to scroll all the way to the end. offsetY / offsetX shift the landing point, which is how you keep a fixed header from covering the section you just scrolled to.
autoKill: true cancels the tween the moment the user scrolls manually, so the animation stops instead of fighting a person who has decided to take over. On a scroll-to that's almost always what you want.
Ease choice for scroll-to
expo.out default used for UI. power2.inOut or power3.inOut accelerates off the start and settles into the target, which feels like intentional travel rather than a yank.Use it for
- Anchor navigation that glides to a section instead of jumping (
a href="#pricing") - Scroll-to-top buttons
- Landing a section under a fixed header using
offsetY - Scrolling an inner overflow container (a chat log, a sidebar) to top, bottom, or a specific row
- Moving the user to the next step in a multi-section form or onboarding flow
Use something else when
ScrollToPlugin is only worth pulling in when you need control over the motion. If you don't, lighter options exist.
- Plain jump-to-anchor with no custom easing needed, use CSS
scroll-behavior: smoothon thehtmlelement, no JS at all - Scroll position should DRIVE an animation (parallax, pinning, scrubbed reveals), that's
ScrollTrigger, not ScrollToPlugin, they solve opposite problems - You want the entire page to scroll with momentum and inertia, reach for
ScrollSmootheror Lenis, not a per-click scroll-to - You only need to detect scroll direction or swipe gestures, use
Observer
Respect reduced motion
prefers-reduced-motion. As of the 2024 Web Almanac, more than 50% of mobile sites ship a prefers-reduced-motion query, up from 34% in 2022, making it the most-adopted user-preference media query. When reduce is set, drop duration to 0 (or use window.scrollTo directly) so the page jumps instead of animating. Gate it once with gsap.matchMedia().Where scroll-to fits in Annnimate components
Scroll-to is the companion to navigation, so the components it belongs with are the nav surfaces. In the Annnimate library the two obvious homes are the sticky header and the mega menu, whose links are the things a reader clicks to move around a page.
- The Hide Header component keeps a nav bar accessible by hiding on scroll-down and returning on scroll-up. Its links ship as
#placeholders, wire them to real section IDs with a ScrollToPlugin tween andoffsetYset to the header height, and clicking a nav item glides the reader down without the sticky bar covering the target - The Mega Menu exposes a full column of links per group. Point those at in-page sections and route the click through a scroll-to tween so the menu closes and the page travels to the section in one motion
Neither component bundles ScrollToPlugin by default (the demos link to #), it's the natural next step when you drop these into a real single-page site with sections to navigate between.
See it running in production
Common questions
- How do I smooth-scroll to an anchor with GSAP?
- Register ScrollToPlugin, then tween the window:
gsap.to(window, { duration: 0.9, ease: 'power3.inOut', scrollTo: { y: '#section', offsetY: 72 } }). Theyvalue accepts a selector, an element, or a pixel number, andoffsetYkeeps a fixed header from covering the target. Intercept the anchor's click withpreventDefault()first so the browser's native instant jump doesn't fire. - ScrollToPlugin vs CSS scroll-behavior: smooth, which should I use?
- If you just want a plain smooth jump and don't care about the timing, use CSS
scroll-behavior: smooth, it's one line and needs no JS. Reach for ScrollToPlugin when you need control the CSS property can't give you: a specific duration and ease, anoffsetYfor a fixed header,autoKillso a manual scroll cancels it, or scrolling an inner container instead of the window. - Do I need ScrollTrigger to use ScrollToPlugin?
- No. They're separate plugins that do opposite things. ScrollToPlugin MOVES the scroll position (you tell the page where to go). ScrollTrigger READS the scroll position to drive animations (the page tells your tween where it is). Register whichever you need, or both if you have scroll-driven effects and jump-to-section links on the same page.
- How do I offset the scroll target so my fixed header doesn't cover it?
- Set
offsetY(oroffsetX) inside thescrollToobject to the height of the fixed element:scrollTo: { y: '#section', offsetY: 80 }lands the section 80px below the top, clear of an 80px header. This is cleaner than adding invisible padding orscroll-margin-topto every section. - My scroll-to animation fights the user when they try to scroll, how do I stop it?
- Add
autoKill: trueto thescrollToobject. When the user scrolls manually mid-tween, GSAP kills the animation instead of dragging them back to the target. Without it, a long scroll-to can feel like the page is wrestling control away from someone who has decided to go somewhere else.
