Page not scrolling to top when route changes in Nuxt JS
Asked Answered
E

10

8

I'm trying to always go on the top of the page when route changes with Nuxt.

So I've put this into my app/router.scrollBehavior.js file:

export default function (to, from, savedPosition) {
  return { x: 0, y: 0 }
}

But it always returns to the last saved position (which is always null in my console by the way).

Any idea of what I could miss here?

Edin answered 9/11, 2021 at 18:5 Comment(15)
Does this answer your question? How not to scroll up page after changing route in Nuxt jsConfluence
Thanks @kissu, but no. I'd like the exact opposite behavior : always scroll up, or even better (with a transition maybe), always arriving at the top of the page without scrolling.Edin
Hi, did you opened the linked question? It was poorly named, but still please give it a read. Because at the end, it is explaining how the whole scrolling behavior works in Nuxt, hence you should be able to have it working regardless of what you're trying to achieve here.Confluence
Hi @kissu, no I didn't, but I'm gonna do that now and give you my feedback after that. Thanks for the link :)Edin
@Confluence sorry, but this didn't help me. I tried all the solutions but nothing worked for me.Edin
Please add more details on what you've tried, what is not working and maybe give us a minimal reproducible example to help you faster!Confluence
Yes, i was thinking about making a codesandbox and maybe I'll understand something important during the process :)Edin
@Confluence well... in my minimal demo here: codesandbox.io/s/mystifying-bush-l2v6z, all works as expected (besides it seems that this is the default behavior of Nuxt to always return on top when route changes). So maybe I've something that blocks this natural behavior. Maybe a GSAP timeline that isn't destroyed on route changes. I'm gonna inspect this a little bit further.Edin
You probably have a typo somewhere? Or something pretty simple that may conflict with the scroll behavior?Confluence
@Confluence It seems that its related to some GSAP scroll animations. When I disable them, almost everything is working fine :)Edin
Yeah, be careful when mixing those libraries. Btw, I do have this question, not sure if it may interest you: https://mcmap.net/q/1321386/-nuxt-with-locomotivescroll-and-gsapConfluence
Also, if your issue is solved. Mind if I post an answer stating that it was basically a GSAP conflict?Confluence
Yes @kissu, no problem for me that you post an answer. I made a copy of my project and disabled Gsap everywhere to be sure and all is working fine. I've spotted some places where I don't destroy the timelines and/or scrollTriggers, so I guess this is where my problem is located. For your question on LocomotiveScroll, there is a great tutorial on how to implement it with GSAP step by step here : creativecodingclub.com/courses/scrolltrigger-express (10$ a month)Edin
Haha, the linked question is not one of mine, I've actually answered to this one.Confluence
@kissu, yes I saw this :)Edin
C
16

For Nuxt v3.0.0-rc.3

Create file named route.global.ts on middleware/ folder

Then write this in file:

export default defineNuxtRouteMiddleware((to, from) => {
  if (to.path !== from.path && process.client) {
    window.scrollTo(0, 0)
  }
})
Cog answered 23/5, 2022 at 15:3 Comment(1)
Still working on RC12 for the record.Hyetograph
C
12

I use Nuxt 3 (npm:[email protected]), none of the solutions work for me. Finally this works:

/plugins/scrollToTop.js (any filename will work, just put it in the plugins folder)

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.$router.options.scrollBehavior = async (to, from, savedPosition) => {
    if (to.path !== from.path && process.client) {
      window.scrollTo(0, 0);
    }
  };
});
Crawford answered 27/7, 2022 at 5:47 Comment(0)
P
5

For Nuxt 3

My solution was to create a file in the middleware folder with the following stucture:

export default defineNuxtRouteMiddleware((to, from) => {
  useNuxtApp().hook("page:finish", () => {
    if (history.state.scroll) {
      setTimeout(() => window.scrollTo(history.state.scroll), 0);
    } else {
      setTimeout(() => window.scrollTo(0, 0), 0);
    }
  });
})

and I named it fix-scroll-position.global.ts.

The setTimeout is used to avoid the weird jumping to the top, meaning that the user won't see the page scrolling to the top.

This snippet ensures that the page scrolls to the top when the routes change, and that the scroll position is kept when the back button is clicked. The last functionality is achieved using history.state.scroll, that checks if there is a scroll position saved from the previous route.

Pleurodynia answered 18/10, 2022 at 9:45 Comment(1)
PS: this answer is for Nuxt3.Confluence
A
3

The top answer is not the correct way of doing it.

Create a file in app directory called router.options.js

// app/router.options.js
export default {
  scrollBehavior() {
    return { top: 0 }
  }
}

With typescript (recommended)

// app/router.options.ts
import type { RouterOptions } from '@nuxt/schema'

export default <RouterOptions> {
  scrollBehavior() {
    return { top: 0 }
  }
}
Adkinson answered 29/9, 2022 at 10:2 Comment(5)
I wouldn't say that it's not correct, it serves a different purpose while still being flexible (if you don't want that behavior everywhere). It's less generic/global but it is achieving the same result.Confluence
The scroll behavior might (actually should) change, since it’s a bit glitchy rn. The correct way to configure scroll behavior is through the scrollBehavior config. When the scrolling bug is fixed, the scroll will look much better than with the middleware “trick”.Adkinson
What I mean is that both solutions are viable, depends if you want it fully global or in a middleware. Thanks for your input tho!Confluence
this solution, first scrolls to top and then changes the route. what I think the OP is asking is to change the route to the top, not route to top and then change.Efface
This is currently not possible in nuxt unfortunately… sucksAdkinson
R
2

According to the documentation:

https://nuxtjs.org/docs/configuration-glossary/configuration-router#scrollbehavior

The router.scrollBehavior.js file must be in the app folder, which in turn is in the project's root.

the file should name router.scrollBehavior.js.

You can console.log something in this function and check if it works.

Regalado answered 9/11, 2021 at 18:46 Comment(1)
Thanks @Cianekjr, I forgot the "router." part in my question. It's how I named it in fact, so my question remains.Edin
C
2

At the end, GSAP was conflicting with OP's scrolling behavior.
Removing it, solved all the issues related to Nuxt, nothing was actually wrong with the router.scrollBehavior.js file.

Confluence answered 11/11, 2021 at 16:20 Comment(2)
How do you find out if this is the case @kissu?What
@BorisKamp in OP's case that was the issue. If you want to see if it's the same in your case, you can probably try to remove it from your project! I mean, that or anything that may conflict with the default behavior of some scroll interaction.Confluence
P
1

I don't have enough reputation for a comment, so therefore an answer. A simple note, but I think it may help some.

I struggled with this as well and nothing worked, but after a while I found out the culprit. My layout looked like this

<template>

  <div id="page" class="flex flex-col h-screen overflow-scroll bg-white">
    <Navbar />

    <slot />

    <Footer />
  </div>
</template>

That div around the components has the height of the screen and the page content scrolls in that div, but therefore the window is always at the top and you won't see any scrolling when clicking on NuxtLink.

I use nuxt 3.0.0 and when I let the #page div grow with the content (ie. removing the h-screen and overflow-scroll tailwind classes), it has the scroll to top behavior even without the solutions from above.

So, if you have this problem with the stable nuxt 3 version, check your html.

Padova answered 18/1, 2023 at 23:23 Comment(1)
This is totally fine as an answer tbh.Confluence
A
0

The current default behavior fixed this issue and behaves just like a native link change. Please remove any custom scrollBehavior configuration and update to the newest version of Nuxt.

Adkinson answered 7/5, 2023 at 20:55 Comment(1)
You should probably edit your other answer here: https://mcmap.net/q/1238278/-page-not-scrolling-to-top-when-route-changes-in-nuxt-jsConfluence
R
0

The default scroll behaviour of Nuxt is scrolling to Top with a smooth behaviour. I my case this wasn't something I want.

I needed a router which scroll to top without smooth behaviour, which goes to hashes with a smooth behaviour and respects the scrollMargin Property and scroll to savedPosition.

This is my suggestion for Nuxt3 (3.6.1)

/app/router.options.js

const scrollToElement = (hashElement) => {
  const element = document.querySelector(hashElement);
  if (element) {
    let scrollMargin = 0 // default there is no scrollMargin
    // read elements scrollMargin if it has one in css
    const style = window.getComputedStyle(element); // Get all styles of an element
    if (style.scrollMarginTop) scrollMargin = parseInt(style.scrollMarginTop);
    window.scrollTo({ top: element.offsetTop - scrollMargin, behavior: "smooth" }); 
  }
};

export default {
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) window.scrollTo(savedPosition);
    else if (to.hash && from.path === to.path) {
      scrollToElement(to.hash);
    } else if (to.hash && from.path !== to.path) { // if hash is on a different page
      useNuxtApp().hook("page:transition:finish", () => {
        scrollToElement(to.hash);
      });
    }
    
    else if (to.path !== from.path){

      // Wait until the page is rendered
      // Otherwise it scrolls to top when the transition starts 
      // before the actually page is changed
      useNuxtApp().hook("page:transition:finish", () => {
        window.scrollTo(0, 0);
      });
    }
  },
};
Ruble answered 13/7, 2023 at 15:32 Comment(0)
V
0

I did this in Nuxt 3 to achieve:

  1. Scroll always to a saved position, if it's set
  2. Scroll to the hash if it is present
  3. Scroll to the top if the two previous conditions are not met

This code goes in app/router.options.ts

import type {
  RouterConfig
} from "nuxt/schema";

export default < RouterConfig > {
  scrollBehavior(to, from, savedPosition) {
    return savedPosition ?
      savedPosition :
      to.hash ?
      {
        el: to.hash
      } :
      {
        top: 0
      };
  },
};

Nuxt uses the vue router under the hood, so you can see the details here https://router.vuejs.org/guide/advanced/scroll-behavior.html

Vaporish answered 24/7, 2023 at 23:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.