
Security News
npm Adopts OIDC for Trusted Publishing in CI/CD Workflows
npm now supports Trusted Publishing with OIDC, enabling secure package publishing directly from CI/CD workflows without relying on long-lived tokens.
@swup/scroll-plugin
Advanced tools
A swup plugin for customizable smooth scrolling.
Install the plugin from npm and import it into your bundle.
npm install @swup/scroll-plugin
import SwupScrollPlugin from '@swup/scroll-plugin';
Or include the minified production file from a CDN:
<script src="https://unpkg.com/@swup/scroll-plugin@4"></script>
To run this plugin, include an instance in the swup options.
const swup = new Swup({
plugins: [new SwupScrollPlugin()]
});
Scroll Plugin works out of the box for sites where the window
is the main scroll container,
scrolling back up on page visits and restoring the previous position on browser history visits.
If your site has other scroll containers than the window
, like overflowing divs, the plugin will
happily restore their scroll positions as long as you let it know about those containers. You can
either add the attribute [data-swup-scroll-container]
to them or use the
scrollContainers option to configure a custom selector.
On each page navigation, the plugin will reset the scroll position to the top just like the browser would. On backword/forward history visits, it will restore the previous scroll position that was saved right before leaving the page.
You can customize when to reset vs. restore while clicking a link using the shouldResetScrollPosition option. A common use case would be a custom back button: clicking it would normally reset the scoll position to the top while users would expect it to restore the previous scroll position on the page the link points towards.
doScrollingRightAway
defines if swup is supposed to wait for the replace of the page to scroll to the top.
animateScroll
defines whether the scroll animation is enabled or swup simply sets the scroll
without animation instead. Passing true
or false
will enable or disable all scroll animations.
For finer control, you can pass an object:
{
animateScroll: {
betweenPages: true,
samePageWithHash: true,
samePage: true
}
}
š” We encourage you to respect user preferences when setting the animateScroll
option:
// Using a simple boolean...
{
animateScroll: !window.matchMedia('(prefers-reduced-motion: reduce)').matches
}
// ...or this little monster, with full control over everything:
{
animateScroll: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? false : {
betweenPages: true,
samePageWithHash: true,
samePage: true
}
}
Customize how the scroll target is found on the page. Defaults to standard browser behavior (#id
first, a[name]
second).
{
// Use a custom data attribute instead of id
getAnchorElement: (hash) => {
hash = hash.replace('#', '')
return document.querySelector(`[data-scroll-target="${hash}"]`)
}
}
Due to certain limitations of the History API,
the :target
CSS pseudo-class stops
working on sites that push their own history entries, which includes any site using swup. Enabling
this option provides an alternative way of styling the current target element.
Navigating to the URL /index.html#section2
will make the following element the target element:
<section id="section2">Example</section>
To highlight the current target element, use the data-swup-scroll-target
attribute for styling:
[data-swup-scroll-target] {
outline: 5px auto blue;
}
Offset to substract from the final scroll position, to account for fixed headers. Can be either a
static number or a function that returns a value based on the scroll target. To apply differing
offsets for vertical and horizontal scrolling, return an object with top
and left
properties.
{
// Number: fixed offset in px
offset: 30,
// Object: fixed vertical and horizontal offset in px
offset: { top: 30, left: 10 },
// Function: calculate offset before scrolling
offset: () => document.querySelector('#header').offsetHeight,
// The scroll target and container are passed into the function
offset: (scrollTarget, scrollContainer) => target.offsetHeight * 2,
}
Customize the selector string used for finding scroll containers other than the window
. See the
Scroll Containers section for an explanation of how the plugin deals with
overflowing containers.
{
// Always restore the scroll position of overflowing tables and sidebars
scrollContainers: '.overflowing-table, .overflowing-sidebar'
}
Callback function that allows customizing the behavior when a link is clicked. Instead of scrolling
back up on page visits, returning false
here will instead restore the previous scroll position
recorded for that page. See Reset vs. restore for an explanation and use cases.
{
// Don't scroll back up for custom back-links, mimicking the browser back button
shouldResetScrollPosition: (link) => !link.matches('.backlink')
}
new SwupScrollPlugin({
doScrollingRightAway: false,
animateScroll: {
betweenPages: true,
samePageWithHash: true,
samePage: true
},
getAnchorElement: null,
markScrollTarget: false,
offset: 0,
scrollContainers: `[data-swup-scroll-container]`,
shouldResetScrollPosition: (link) => true,
scrollFunction: undefined
});
Scroll Plugin adds the method scrollTo
to the swup instance, which can be used for custom scrolling.
The method accepts a scroll position in pixels and a boolean whether the scroll position should be animated:
// will animate the scroll position of the window to 2000px
swup.scrollTo(2000, true);
The plugin adds two new hooks scroll:start
and scroll:end
:
swup.hooks.on('scroll:start', () => console.log('Swup started scrolling'));
swup.hooks.on('scroll:end', () => console.log('Swup finished scrolling'));
You can overwrite the scroll function with your own implementation by passing it in as the
scrollFunction
option. This way, you gain full control over how you animate your scroll positions.
Below is an example using GSAP's
ScrollToPlugin.
Note that you are responsible for calling the start
and end
functions passed to the scroll
function to let swup correctly trigger the scroll:start
and scroll:end
hooks.
import Swup from 'swup';
import SwupScrollPlugin from '@swup/scroll-plugin';
import { gsap } from 'gsap';
import ScrollToPlugin from 'gsap/ScrollToPlugin';
gsap.registerPlugin(ScrollToPlugin);
/**
* Use GSAP ScrollToPlugin for animated scrolling
* @see https://greensock.com/docs/v3/Plugins/ScrollToPlugin
*/
new Swup({
plugins: [
new SwupScrollPlugin({
scrollFunction: (el, top, left, animate, start, end) => {
gsap.to(el, {
duration: animate ? 0.6 : 0,
ease: "power4.out",
scrollTo: {
y: top,
x: left,
autoKill: window.matchMedia("(hover: hover)").matches,
onAutoKill: () => end(),
},
onStart: () => start(),
onComplete: () => end(),
});
},
}),
]
});
[4.0.0] - 2025-08-04
scrollFunction
to customize the scroll implementationFAQs
A swup plugin for customizable smooth scrolling
The npm package @swup/scroll-plugin receives a total of 13,011 weekly downloads. As such, @swup/scroll-plugin popularity was classified as popular.
We found that @swup/scroll-plugin demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Ā It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
npm now supports Trusted Publishing with OIDC, enabling secure package publishing directly from CI/CD workflows without relying on long-lived tokens.
Research
/Security News
A RubyGems malware campaign used 60 malicious packages posing as automation tools to steal credentials from social media and marketing tool users.
Security News
The CNA Scorecard ranks CVE issuers by data completeness, revealing major gaps in patch info and software identifiers across thousands of vulnerabilities.