{"id":27952111,"url":"https://github.com/swup/scroll-plugin","last_synced_at":"2025-07-30T14:13:05.737Z","repository":{"id":40659909,"uuid":"184438671","full_name":"swup/scroll-plugin","owner":"swup","description":"A swup plugin for smooth scrolling 🏄‍♂️","archived":false,"fork":false,"pushed_at":"2024-09-28T17:04:09.000Z","size":1414,"stargazers_count":3,"open_issues_count":3,"forks_count":8,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-04T07:48:08.406Z","etag":null,"topics":["acceleration","animation","page-transitions","plugin","scroll","swup"],"latest_commit_sha":null,"homepage":"https://swup.js.org/plugins/scroll-plugin","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/swup.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["gmrchk","daun","hirasso"],"open_collective":"swup"}},"created_at":"2019-05-01T15:36:21.000Z","updated_at":"2024-09-28T17:04:05.000Z","dependencies_parsed_at":"2024-09-15T12:53:16.878Z","dependency_job_id":"cc561b29-ff1d-4205-b711-077234aba8d3","html_url":"https://github.com/swup/scroll-plugin","commit_stats":{"total_commits":171,"total_committers":6,"mean_commits":28.5,"dds":0.5730994152046784,"last_synced_commit":"45c97025c8ea1084b4e75821e624f41cda52363b"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swup%2Fscroll-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swup%2Fscroll-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swup%2Fscroll-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swup%2Fscroll-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/swup","download_url":"https://codeload.github.com/swup/scroll-plugin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252914728,"owners_count":21824425,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acceleration","animation","page-transitions","plugin","scroll","swup"],"created_at":"2025-05-07T16:27:35.203Z","updated_at":"2025-05-07T16:27:35.971Z","avatar_url":"https://github.com/swup.png","language":"TypeScript","funding_links":["https://github.com/sponsors/gmrchk","https://github.com/sponsors/daun","https://github.com/sponsors/hirasso","https://opencollective.com/swup"],"categories":[],"sub_categories":[],"readme":"# Swup Scroll plugin\n\nA [swup](https://swup.js.org) plugin for customizable smooth scrolling.\n\n- Enables acceleration-based smooth scrolling\n- Animates scroll position between page visits\n- Animates scrolling to anchors\n- Define a custom offset for scroll positions\n- Emulate scroll target selector\n\n## Installation\n\nInstall the plugin from npm and import it into your bundle.\n\n```bash\nnpm install @swup/scroll-plugin\n```\n\n```js\nimport SwupScrollPlugin from '@swup/scroll-plugin';\n```\n\nOr include the minified production file from a CDN:\n\n```html\n\u003cscript src=\"https://unpkg.com/@swup/scroll-plugin@3\"\u003e\u003c/script\u003e\n```\n\n## Usage\n\nTo run this plugin, include an instance in the swup options.\n\n```javascript\nconst swup = new Swup({\n  plugins: [new SwupScrollPlugin()]\n});\n```\n\n## Behavior\n\nScroll Plugin works out of the box for sites where the `window` is the main scroll container,\nscrolling back up on page visits and restoring the previous position on browser history visits.\n\n### Scroll containers\n\nIf your site has other scroll containers than the `window`, like overflowing divs, the plugin will\nhappily restore their scroll positions as long as you let it know about those containers. You can\neither add the attribute `[data-swup-scroll-container]` to them or use the\n[scrollContainers](#scrollcontainers) option to configure a custom selector.\n\n### Reset vs. restore\n\nOn each page navigation, the plugin will **reset** the scroll position to the top just like the\nbrowser would. On backword/forward history visits, it will **restore** the previous scroll position\nthat was saved right before leaving the page.\n\nYou can customize when to reset vs. restore while clicking a link using the\n[shouldResetScrollPosition](#shouldresetscrollposition) option. A common use case would be a\ncustom back button: clicking it would normally reset the scoll position to the top while users would expect it\nto restore the previous scroll position on the page the link points towards.\n\n## Options\n\n### doScrollingRightAway\n\n`doScrollingRightAway` defines if swup is supposed to wait for the replace of the page to scroll to the top.\n\n### animateScroll\n\n`animateScroll` defines whether the scroll animation is enabled or swup simply sets the scroll\nwithout animation instead. Passing `true` or `false` will enable or disable all scroll animations.\nFor finer control, you can pass an object:\n\n```javascript\n{\n  animateScroll: {\n    betweenPages: true,\n    samePageWithHash: true,\n    samePage: true\n  }\n}\n```\n\n💡 We encourage you to respect user preferences when setting the `animateScroll` option:\n\n```javascript\n// Using a simple boolean...\n{\n  animateScroll: !window.matchMedia('(prefers-reduced-motion: reduce)').matches\n}\n// ...or this little monster, with full control over everything:\n{\n  animateScroll: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? false : {\n    betweenPages: true,\n    samePageWithHash: true,\n    samePage: true\n  }\n}\n```\n\n### scrollFriction and scrollAcceleration\n\nThe animation behavior of the scroll animation can be adjusted by setting `scrollFriction` and `scrollAcceleration`.\n\n### getAnchorElement\n\nCustomize how the scroll target is found on the page. Defaults to standard browser behavior (`#id` first, `a[name]` second).\n\n```javascript\n{\n  // Use a custom data attribute instead of id\n  getAnchorElement: (hash) =\u003e {\n    hash = hash.replace('#', '')\n    return document.querySelector(`[data-scroll-target=\"${hash}\"]`)\n  }\n}\n```\n\n### markScrollTarget\n\nDue to [certain limitations](https://github.com/whatwg/html/issues/639) of the History API,\nthe [`:target` CSS pseudo-class](https://developer.mozilla.org/en-US/docs/Web/CSS/:target) stops\nworking on sites that push their own history entries, which includes any site using swup. Enabling\nthis option provides an alternative way of styling the current target element.\n\nNavigating to the URL `/index.html#section2` will make the following element the target element:\n\n```html\n\u003csection id=\"section2\"\u003eExample\u003c/section\u003e\n```\n\nTo highlight the current target element, use the `data-swup-scroll-target` attribute for styling:\n\n```css\n[data-swup-scroll-target] {\n  outline: 5px auto blue;\n}\n```\n\n### Offset\n\nOffset to substract from the final scroll position, to account for fixed headers. Can be either a number or a function that returns the offset.\n\n```javascript\n{\n  // Number: fixed offset in px\n  offset: 30,\n\n  // Function: calculate offset before scrolling\n  offset: () =\u003e document.querySelector('#header').offsetHeight,\n\n  // The scroll target element is passed into the function\n  offset: target =\u003e target.offsetHeight * 2,\n}\n```\n\n### scrollContainers\n\nCustomize the selector string used for finding scroll containers other than the `window`. See the\n[Scroll Containers](#scroll-containers) section for an explanation of how the plugin deals with\noverflowing containers.\n\n```js\n{\n  // Always restore the scroll position of overflowing tables and sidebars\n  scrollContainers: '.overflowing-table, .overflowing-sidebar'\n}\n```\n\n### shouldResetScrollPosition\n\nCallback function that allows customizing the behavior when a link is clicked. Instead of scrolling\nback up on page visits, returning `false` here will instead restore the previous scroll position\nrecorded for that page. See [Reset vs. restore](#reset-vs-restore) for an explanation and use cases.\n\n```js\n{\n  // Don't scroll back up for custom back-links, mimicking the browser back button\n  shouldResetScrollPosition: (link) =\u003e !link.matches('.backlink')\n}\n```\n\n### Default options\n\n```javascript\nnew SwupScrollPlugin({\n  doScrollingRightAway: false,\n  animateScroll: {\n    betweenPages: true,\n    samePageWithHash: true,\n    samePage: true\n  },\n  scrollFriction: 0.3,\n  scrollAcceleration: 0.04,\n  getAnchorElement: null,\n  markScrollTarget: false,\n  offset: 0,\n  scrollContainers: `[data-swup-scroll-container]`,\n  shouldResetScrollPosition: (link) =\u003e true\n});\n```\n\n## Methods on the swup instance\n\nScroll Plugin adds the method `scrollTo` to the swup instance, which can be used for custom scrolling.\nThe method accepts a scroll position in pixels and a boolean whether the scroll position should be animated:\n\n```js\n// will animate the scroll position of the window to 2000px\nswup.scrollTo(2000, true);\n```\n\n## Hooks\n\nThe plugin adds two new hooks `scroll:start` and `scroll:end` :\n\n```js\nswup.hooks.on('scroll:start', () =\u003e console.log('Swup started scrolling'));\nswup.hooks.on('scroll:end', () =\u003e console.log('Swup finished scrolling'));\n```\n\n## Overwriting `swup.scrollTo`\n\nYou can overwrite the scroll function with your own implementation. This way, you can gain full control over how you animate your scroll positions. Here's an example using [GSAP's](https://greensock.com/docs/v3/) [ScrollToPlugin](https://greensock.com/docs/v3/Plugins/ScrollToPlugin):\n\n```js\n\nimport Swup from 'swup';\nimport SwupScrollPlugin from '@swup/scroll-plugin';\n\nimport { gsap } from 'gsap';\nimport ScrollToPlugin from 'gsap/ScrollToPlugin';\ngsap.registerPlugin(ScrollToPlugin);\n\nconst swup = new Swup({\n\tplugins: [new SwupScrollPlugin()]\n});\n\n/**\n * Overwrite swup's scrollTo function\n */\nswup.scrollTo = (offsetY, animate = true) =\u003e {\n\tif (!animate) {\n\t\tswup.hooks.callSync('scroll:start', undefined);\n\t\twindow.scrollTo(0, offsetY);\n\t\tswup.hooks.callSync('scroll:end', undefined);\n\t\treturn;\n\t}\n\n\t/**\n\t * Use GSAP ScrollToPlugin for animated scrolling\n\t * @see https://greensock.com/docs/v3/Plugins/ScrollToPlugin\n\t */\n\tgsap.to(window, {\n\t\tduration: 0.8,\n\t\tscrollTo: offsetY,\n\t\tease: 'power4.inOut',\n\t\tautoKill: true,\n\t\tonStart: () =\u003e {\n\t\t\tswup.hooks.callSync('scroll:start', undefined);\n\t\t},\n\t\tonComplete: () =\u003e {\n\t\t\tswup.hooks.callSync('scroll:end', undefined);\n\t\t},\n\t\tonAutoKill: () =\u003e {\n\t\t\tswup.hooks.callSync('scroll:end', undefined);\n\t\t},\n\t});\n\n};\n\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswup%2Fscroll-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswup%2Fscroll-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswup%2Fscroll-plugin/lists"}