Anchor in Nuxt component not working on same page the anchor is included on

Viewed 3427

In my Footer Component I have this to link to the owners bio on the about page

 <nuxt-link :to="{path: '/about', hash: 'alex'}">Alex</nuxt-link>

In the about/index.vue file I have the anchor

 <hr class="my-5" id="alex" />
    <h2 style>
      Alex
      <br />
      <span style="font-size: 16px; font-weight: bold;">Co-Founder and Partner</span>
    </h2>

On all pages this works when you click the link in the footer. It does not work if you are on the about page and click the footer link.

What can I do to make this also work on the about page?

4 Answers

Update Nuxt Link as below

<nuxt-link :to="{path: '/about', hash: '#alex'}">Alex</nuxt-link>

++ Updated

Need to add scroll behavior in nuxt.config.js as below

  router: {
    scrollBehavior: async function(to, from, savedPosition) {
      if (savedPosition) {
        return savedPosition;
      }

      const findEl = async (hash, x = 0) => {
        return (
          document.querySelector(hash) ||
          new Promise(resolve => {
            if (x > 50) {
              return resolve(document.querySelector("#app"));
            }
            setTimeout(() => {
              resolve(findEl(hash, ++x || 1));
            }, 100);
          })
        );
      };

      if (to.hash) {
        let el = await findEl(to.hash);
        if ("scrollBehavior" in document.documentElement.style) {
          return window.scrollTo({ top: el.offsetTop, behavior: "smooth" });
        } else {
          return window.scrollTo(0, el.offsetTop);
        }
      }

      return { x: 0, y: 0 };
    }
  },

Codesandbox Link

You can use vue-scrollto package also and if you are using Vuetify with Nuxtjs than there is $vuetify.goTo available.

Just wanted to add, if people are stuck, you can add a file called router.scrollBehavior.js in your nuxt project:

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

Unfortunately, there are issues with it firing before the render - you can use nuxt/vue tick if you correctly import - but this still seems to work ( for anchors and for saved positions ):

export default async function (to, from, savedPosition) {


if (savedPosition) {
    console.log("SAVED POSITION");
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({
          selector: savedPosition
        });
      }, 600);
    });
    // not working consistently due to render
    //return savedPosition;
}
else if (to.hash) {
    console.log("HASH");
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        selector: to.hash
      });
    }, 600);
  });
}
else {
    console.log("NORMAL");
    return { x: 0, y: 0 };
}}

I am using Nuxt 3 and having the same problem, I solved the problem using this with thoughts of helping Nuxt 3 devs with same problem

Anchor tag with NuxtLink

<NuxtLink :to="{path: '/about', hash: '#support'}">Support</NuxtLink>

On the Nuxt page <script setup>

// Make sure you are in the client
// browser to access `document` variable
if (process.client) {

  // get current route
  const {currentRoute : route} = useRouter();
  
  // make sure that hash is defined
  if (route.value?.hash) {

      // set hash
      const hash = route.value?.hash

      // use onMounted hook to run the code inside 
      // after the page is mounted to the DOM
      onMounted(() => {
       
        // get target element
        let el = document.querySelector(hash)

        // make sure that the element exists then scroll to that element
        if(el) {
          if ('scrollBehavior' in document.documentElement.style) {
            window.scrollTo({ top: el.getBoundingClientRect().top+window.scrollY, behavior: 'smooth' })
          } else {
            window.scrollTo(0, el.getBoundingClientRect().top+window.scrollY)
          }
        }
      })
  }
}

If your are on Vue 3, you will have to create a file here app/router.options.ts with the following code inside

import type { RouterConfig } from '@nuxt/schema'

// https://router.vuejs.org/api/#routeroptions
export default <RouterConfig>{
   scrollBehavior(to, from, savedPosition) {
     return { el: to.hash }
   }
}

Your nuxt link should look like this

<NuxtLink :to="{ path: '/', hash: '#projects' }">Projects</NuxtLink>

Checkout more more

Related