Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJS scroll to section from different route

I am trying to scroll to an anchor on a page using Vue and Vue Router (with history mode).

When on the index page, the scroll behaviour works as expected by jumping to the section.

However, when I am another page, it loads the index page at the top and not where the anchor is pointing to.

I’m sure it’s a very simple thing but can’t get my head round it!

Any help is appreciated!

My router index:

export default new Router({
  scrollBehavior: function(to, from, savedPosition) {
    if (to.hash) {
      return {selector: to.hash}
    } else {
      return {x: 0, y: 0}
    }
  },

  mode: 'history',
  routes: [ ... ]
})

My Navigation:

<router-link @click.native="closeNav" to="/#enter">Enter</router-link>
<router-link @click.native="closeNav" to="/#prizes">Prizes</router-link>
<router-link @click.native="closeNav" to="/#faqs">FAQ</router-link>
<router-link @click.native="closeNav" to="/contactus">Contact</router-link>
like image 914
Jack McLaughlin Avatar asked Dec 13 '22 15:12

Jack McLaughlin


2 Answers

Vue Router v3.x

This is a bit of an old question and OP has almost surely found a solution already, but for anyone running into this problem, this should do the trick:

    <router-link :to="{ name: 'Homepage', hash: '#enter' }">Enter</router-link>
    <router-link :to="{ name: 'Homepage', hash: '#prizes' }">Prizes</router-link>
    <router-link :to="{ name: 'Homepage', hash: '#faqs' }">FAQ</router-link>
    <router-link :to="{ name: 'Contact' }">Contact</router-link>

This should allow you to have these links accessible from other views/components, and when clicked will redirect you to the named route (Homepage in this case), and scroll to the hash specified (#enter, #prizes, #faqs).

In addition to the router code snippet in the question, you can add smooth scrolling using the native window.scrollTo method:

    export default new Router({
      routes: [],
      mode: 'history',
      scrollBehavior (to, from, savedPosition) {
        if (to.hash) {
          return window.scrollTo({ 
            top: document.querySelector(to.hash).offsetTop, 
            behavior: 'smooth' 
          })
        } else {
          return { x: 0, y: 0 }
        }
      }
    })

Update for Vue Router v4.x

You write your router-links the same, but you can write the scroll behavior and element selection a bit neater now. From the docs

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes,
  scrollBehavior(to, from, savedPosition) {
    if (to.hash) {
      return {
        el: to.hash,
        behavior: 'smooth'
      }
    }
  }
})
like image 80
a21y Avatar answered Dec 18 '22 07:12

a21y


I am using scrollIntoView() instead of window.scrollTo()

export default new Router({
  routes: [],
  mode: 'history',
  scrollBehavior (to, from, savedPosition) {
    if (to.hash) {
      return document.querySelector(to.hash).scrollIntoView({ behavior: 'smooth' });
    } else {
      return savedPosition || { x: 0, y: 0 }
    }
  }
})
like image 45
Syed Avatar answered Dec 18 '22 06:12

Syed