swup / parallel-plugin

A swup plugin for animating the previous and next page in parallel  🎏
https://swup.js.org/plugins/parallel-plugin
MIT License
6 stars 1 forks source link

Feature: Match scroll position of outgoing and incoming page #18

Open michalchovanak opened 1 month ago

michalchovanak commented 1 month ago

Describe the problem 🧐

First of all, I appreciate the work done on Swup, it’s great!

I managed to make a beautiful transition for my website with the help of SwupParallelPlugin. It’s basically an easy masked transition to the new page.

I want to be able to click on a link, for example, in the second half of a page, and the next page should be scrolled to the top. I viewed a lot of previous issues, tried various hooks, and tried SwupScrollPlugin, but nothing is working in this manner. The SwupScrollPlugin is closest to what I want to achieve, but it scrolls the actual page to the top and then transitions.

I appreciate all the help.

Describe the propsed solution 😎

So i want this:

  1. page - stay on the position after click on a link
  2. page - opens scrolled to top

Alternatives considered 🤔

SwupScrollPlugin

How important is this feature to you? 🧭

I cannot use swup without it

Checked all these? 📚

daun commented 1 month ago

Hi! I'm not sure I understand 100% what you're trying to achieve. You want the whole animation to finish, and only then scroll to the top?

daun commented 1 month ago

It's probably easiest to understand if you're willing to share a link to your current solution.

michalchovanak commented 1 month ago

@daun Please see this video: https://github.com/user-attachments/assets/6361996d-42a9-48a0-a3b6-a8c831b4b88d

You can see that the page firstly scrolls to top and then transitions to the next page i clicked. I need it to stay static, transition to the next page that is scrolled to top.

daun commented 1 month ago

Alright, thanks.

That should be doable already by disabling the scroll reset and doing it yourself manually.

Untested example code below, let us know if that works. You can probably remove the if {} checks if you're only ever running parallel animations.

swup.hooks.on('visit:start', (visit) => {
  if (visit.animation.parallel) {
    visit.scroll.reset = false
  }
})

swup.hooks.on('visit:end', () => {
  if (visit.animation.parallel) {
    window.scrollTo(0, 0)
  }
})
daun commented 1 month ago

If the scroll needs to be smooth, you can use this function signature:

window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
michalchovanak commented 1 month ago

@daun thanks, visit.scroll.reset = false helped to stop scrolling to top on start. The problem is that the page transitions to the next one and it will scroll to top after the transition to top. I need it to by on top before the transition.

daun commented 1 month ago

I see. That's a CSS question. Mostly. I've done this for a similar project and it's not pretty, but doable. Nothing I can share here, unfortunately, as it wasn't done in swup.

The logic goes like this: You measure the current scroll position when the transition starts, and offset the next page by that amount so it visually lines up with the current viewport. Right when the transition finishes, you remove the offset while simultaneously resetting the window scroll position.