{"id":27952087,"url":"https://github.com/swup/parallel-plugin","last_synced_at":"2025-05-07T16:27:32.691Z","repository":{"id":179656274,"uuid":"663920641","full_name":"swup/parallel-plugin","owner":"swup","description":"A swup plugin for animating the previous and next page in parallel  🎏","archived":false,"fork":false,"pushed_at":"2024-02-15T12:11:03.000Z","size":668,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-05-16T01:10:09.567Z","etag":null,"topics":["animation","page-transitions","parallel","plugin","swup","sync"],"latest_commit_sha":null,"homepage":"https://swup.js.org/plugins/parallel-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},"funding":{"github":["gmrchk","daun","hirasso"],"open_collective":"swup"}},"created_at":"2023-07-08T12:48:55.000Z","updated_at":"2024-04-07T14:12:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"d9e05b5d-63f8-4bed-a568-246e0ee91396","html_url":"https://github.com/swup/parallel-plugin","commit_stats":{"total_commits":76,"total_committers":3,"mean_commits":"25.333333333333332","dds":0.1578947368421053,"last_synced_commit":"f14f5b06616194cf55f95c044676938474c04f52"},"previous_names":["swup/parallel-plugin"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swup%2Fparallel-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swup%2Fparallel-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swup%2Fparallel-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swup%2Fparallel-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/swup","download_url":"https://codeload.github.com/swup/parallel-plugin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252914709,"owners_count":21824422,"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":["animation","page-transitions","parallel","plugin","swup","sync"],"created_at":"2025-05-07T16:27:31.202Z","updated_at":"2025-05-07T16:27:32.670Z","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 Parallel Plugin\n\nA [swup](https://swup.js.org) plugin for animating the previous and next page in parallel.\n\n- Combines swup's leave/enter animations into a single animation\n- Keeps the previous page visible while the next page is entering\n- Allows synchronous animations like overlays, crossfades, or slideshows\n\n## Demos\n\nTo see parallel animations in action, check out the official demos:\n\n- [slideshow animation](https://swup-demo-slideshow.swupjs.repl.co)\n- [reveal animation](https://swup-demo-reveal.swupjs.repl.co)\n\n\u003cdiv data-video data-screencast\u003e\n\nhttps://github.com/swup/parallel-plugin/assets/22225348/aff0a235-d9aa-472b-9967-1e9fa0e67313\n\n\u003c/div\u003e\n\nFeel free to explore more examples on the [Swup Demos](https://swup.js.org/getting-started/demos/) page of the docs.\n\n## Installation\n\nInstall the plugin from npm and import it into your bundle.\n\n```bash\nnpm install @swup/parallel-plugin\n```\n\n```js\nimport SwupParallelPlugin from '@swup/parallel-plugin';\n```\n\nOr include the minified production file from a CDN:\n\n```html\n\u003cscript src=\"https://unpkg.com/@swup/parallel-plugin@0\"\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 SwupParallelPlugin()]\n});\n```\n\n## Scenario\n\nWhen transitioning pages, swup will hide the previous page before replacing the content and showing\nthe next page. This is fine in most cases, and great for performance and accessibility. However,\nsome layouts **require the previous page to be visible for the duration of the page transition**: think\ncrossfades, overlays, slideshows, 3D effects, etc. For these to be convincing, the old and new\ncontainers must be **animated at the same time**.\n\n## Lifecycle\n\n**Swup default animations**\n\n- Animate out: hide the previous content\n- Replace the content entirely\n- Animate in: show the next content\n- Previous and next content are never in the DOM at the same time\n\n**Parallel Plugin animations**\n\n- Skip the out-phase of the animation\n- Add the next content to the DOM\n- Animate in and out: show the next content while hiding the previous content\n- Previous and next content are DOM siblings during the animation\n\n## Markup\n\nIn this example, we want to slide in the new `main` element while sliding out the previous `main`\nelement. The markup for parallel animations isn't any different from normal animations: a simple\nsection with a content area.\n\n```html\n\u003csection\u003e\n  \u003cheader\u003e\n    My Website\n  \u003c/header\u003e\n  \u003cmain id=\"swup\" class=\"transition-slide\"\u003e\n    \u003ch1\u003eWelcome\u003c/h1\u003e\n  \u003c/main\u003e\n\u003c/section\u003e\n```\n\n### State during the animation\n\nDuring the animation, both containers will be in the DOM at the same time.\nSwup has inserted the next container, will wait for any animations to finish, and\nthen remove the previous container.\n\nNote: for accessibility reasons, the next container is always inserted **before** the previous one\nand the previous one is marked as hidden from screen readers by setting `aria-hidden=\"true\"`.\n\n```html\n\u003csection\u003e\n  \u003cheader\u003e\n    My Website\n  \u003c/header\u003e\n  \u003c!-- Next container --\u003e\n  \u003cmain id=\"swup\" class=\"transition-slide is-next-container\"\u003e\n    \u003ch1\u003eNext page\u003c/h1\u003e\n  \u003c/main\u003e\n    \u003c!-- Previous container --\u003e\n  \u003cmain id=\"swup\" class=\"transition-slide is-previous-container\" aria-hidden=\"true\"\u003e\n    \u003ch1\u003ePrevious page\u003c/h1\u003e\n  \u003c/main\u003e\n\u003c/section\u003e\n```\n\n## Styling\n\n### Basic styling for parallel animations\n\nShowing both the previous and current container during a page transition requires slightly more\ncomplex styling than usual. The containers need to be layered on top of each other while they're\nboth in the DOM.\n\nThe details depend on the specific layout, however the easiest way in most cases\nis a CSS `grid` with both containers claiming the same row and column.\nThis type of layout avoids messy absolute positioning and scroll offsets.\n\n```css\n/* Layout */\n\nsection {\n  display: grid;\n  overflow: hidden;\n  grid-template-areas: \"header\"\n                        \"main\";\n}\n\nsection \u003e header {\n  grid-area: header;\n}\n\nsection \u003e main {\n  grid-area: main;\n}\n```\n\n### Defining the animations\n\nInstead of using swup's default classes for timing the animation, parallel animations can be\ncontrolled using two custom classes applied by this plugin on the containers themselves:\n\nThe class `is-previous-container` defines the **final state** of the previous container, e.g.\nalready out of view or transparent. It is added directly after the element is added to the DOM to\nbegin the animation.\n\nThe class `is-next-container` defines the **initial state** of the next container about to enter the\npage, e.g. still out of view or transparent. It is added before the element is inserted into the\nDOM and removed directly after insertion to begin the animation. As it's only applied for a split\nsecond, it won't be visible when inspecting the element in the browser dev tools.\n\n```css\n/* Parallel animation timing */\n.is-changing .transition-slide {\n  transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out;\n}\n\n/* Style of previous container after leaving */\n.transition-slide.is-previous-container {\n  transform: translateX(-100%);\n  opacity: 0;\n}\n\n/* Style of next container before entering */\n.transition-slide.is-next-container {\n  transform: translateX(100%);\n  opacity: 0;\n}\n```\n\n## Timing\n\nTechnically, the plugin will **skip the out-animation**, add the next container, wait for animations to\nfinish, then remove the previous container. **All animations now happen in the in-phase** of the\nlifecycle, after the `content:replace` hook that normally marks the middle of the animation\nprocess. Any containers that are not animated or not animated in parallel (e.g. a static header)\nwill be replaced at the start of the parallel animation.\n\nThis also applies when using the [JS plugin](https://swup.js.org/plugins/js-plugin/): the\nout-animation is skipped entirely and only the in-animation is executed. You'll need to perform\nboth animations in the `in` handler.\n\n## Keeping the previous container\n\nThe previous container is removed from the DOM after the animation finishes. If you need to keep one\nor more copies of it around after the animation, you can set the [keep](#keep) option and adjust\nyour styling.\n\n\u003e **Warning**\n\u003e Keep in mind the accessibility concerns of having duplicate content on the page. While\n\u003e this plugin marks containers as `aria-hidden=\"true\"`, the duplicate content can still be clicked\n\u003e and focussed. Marking previous containers as\n\u003e [inert](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert) is a possible\n\u003e solution but not applicable to all use cases. Turning a `main` container into a simple `div` would\n\u003e be helpful as well, however it's impossible to do without a complete re-render of the element.\n\n```js\nnew SwupParallelPlugin({ keep: 1 })\n```\n\nPrevious containers that will be kept are marked with a class name of `.is-kept-container`. Those\nabout to be removed are marked with `.is-removing-container`.\n\n```html\n\u003csection\u003e\n  \u003cmain id=\"swup\" class=\"transition-slide is-next-container\"\u003e\u003c/main\u003e\n  \u003cmain id=\"swup\" class=\"transition-slide is-previous-container is-kept-container\" aria-hidden=\"true\"\u003e\u003c/main\u003e\n  \u003cmain id=\"swup\" class=\"transition-slide is-previous-container is-kept-container is-removing-container\" aria-hidden=\"true\"\u003e\u003c/main\u003e\n\u003c/section\u003e\n```\n\nUse the classes `is-removing-container` to style the transition of a container to be removed.\n\n```css\n.is-changing .transition-slide {\n  transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out;\n}\n\n.transition-slide.is-next-container {\n  transform: translateX(100%);\n  opacity: 0;\n}\n\n.transition-slide.is-kept-container {\n  transform: translateX(-100%);\n}\n\n.transition-slide.is-removing-container {\n  transform: translateX(-200%);\n  opacity: 0;\n}\n```\n\n## Options\n\n### containers\n\nBy default, all content containers are animated in parallel. If you only want to perform parallel\nanimations for specific containers and replace other containers normally, specify the parallel\ncontainers here.\n\n```js\n{\n  containers: ['main']\n}\n```\n\n### keep\n\nThe number of previous containers to keep around **after** the animation finishes. Useful for layouts\nlike slideshows, stacks, etc. Default: `0`.\n\n```js\n{\n  keep: 1\n}\n```\n\nPass an object indexed by selector to keep around the previous version of certain containers only:\n\n```js\n{\n  containers: ['main', 'footer'],\n  keep: { 'main': 1 }\n}\n```\n\n## API\n\n### Opting out of parallel animations\n\nThe plugin will set a flag on the visit object, indicating the current visit\nas a parallel animation: `visit.animation.parallel`. You can unset this flag\nto fall back to a normal animation with leave and enter in series.\n\n```js\n// Disable parallel animations for this visit\nswup.hooks.on('visit:start', (visit) =\u003e {\n  if (someCondition) {\n    visit.animation.parallel = false;\n  }\n});\n```\n\n## Hooks\n\nThe plugin adds two new hooks to swup. Both hooks receive a `ContainerSet` instance as their\nonly argument:\n\n```ts\ntype ContainerSet = {\n  /** Selector to match this container */\n  selector: string;\n  /** Incoming container element */\n  next: HTMLElement;\n  /** Outgoing container element */\n  previous: HTMLElement;\n  /** Container elements to keep around after the animation */\n  keep: HTMLElement[];\n  /** Container elements to remove after the animation */\n  remove: HTMLElement[];\n};\n```\n\n### `content:insert`\n\nTriggered when the new content containers are inserted. Hook before this to manipulate the\nelements before they are inserted into the DOM.\n\n```js\nswup.hooks.before('content:insert', (visit, { containers }) =\u003e {\n  for (const { next } of containers) {\n    console.log('About to insert container', next);\n  }\n});\n```\n\n### `content:remove`\n\nTriggered when the previous containers are removed, after the animation has finished.\n\n```js\nswup.hooks.before('content:remove', (visit, { containers }) =\u003e {\n  for (const { remove } of containers) {\n    console.log('About to remove containers', remove);\n  }\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswup%2Fparallel-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswup%2Fparallel-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswup%2Fparallel-plugin/lists"}