Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scroll to anchors not working #3

Closed
rijk opened this issue Jun 22, 2020 · 6 comments
Closed

Scroll to anchors not working #3

rijk opened this issue Jun 22, 2020 · 6 comments

Comments

@rijk
Copy link
Contributor

rijk commented Jun 22, 2020

When clicking a link to an #id further down the page, nothing happens. When scroller-motion is disabled, the page jumps to the anchor, but when it is active, no scroll whatsoever. Probably because there is no React state change?

@breadadams
Copy link
Owner

@rijk excuse the delay, I took a look last night and it seems the root cause of the issue is that the anchor's DOM position can't be read (because it's within the scroller-motion element - a position: fixed element).

I'll add this to the roadmap and address it asap, meanwhile you could use a custom solution of locating the offset of the anchored element and then using something like window.scrollTo.

Window scrolling events do work (as you can see in the demo, via the top-right "Scroll down" button).

@rijk
Copy link
Contributor Author

rijk commented Jun 25, 2020

Ahh, I wouldn't have thought of that 😄 Meanwhile, if you have some time could you help me out with #2 as well? I'd love to contribute to the package.

@rijk
Copy link
Contributor Author

rijk commented Aug 12, 2020

I used this workaround for now:

const onClick = ( e ) => {
  e.preventDefault()
  const anchor = e.target.getAttribute( 'href' ).substr( 1 )
  window.scrollTo( 0, document.getElementById( anchor ).offsetTop )
}

@gabrielperales
Copy link

gabrielperales commented Apr 10, 2021

We can add something in the library to intercept hash changes. We can add a flag or something add this event listener to the component:

useEffect(() => {
  const listenHashChange = (e: HashChangeEvent) => {
    const {newURL} = e
    const [_, id] = newURL.match(/#(.*)$/)
    
    if (!id) {
      // scroll to top
      window.scrollTo(0, 0)
    }
    
    const el = document.getElementById(id)
    if (el) {
      // scroll to element
      window.scrollTo(0, el.offsetTop)
    }
  }
  window.addEventListener('hashchange', listenHashChange)
  
  return () => window.removeEventListener('hashchange', listenHashChange)
}, [])

@breadadams
Copy link
Owner

I'm thinking that rather than including this in the "core" we either:

  1. Include it in a new Recipes section of the readme (got a few things in mind we could include there)
  2. Export a hook (i.e. useHashScroll) that users can choose to import/apply to their app, for tree-shaking benefits

@sosnoski
Copy link

Today I had a similar problem using Next 13 and that solution didn't work. However, it worked using router.events. Hope this can help someone:

  const router = useRouter()
  useEffect(() => {
    const onHashChangeStart = (url: string) => {
      const el = document.getElementById(url.slice(2))
      if (el) {
        window.scrollTo(0, el.offsetTop)
      }
    }
    router.events.on('hashChangeStart', onHashChangeStart)
    return () => {
      router.events.off('hashChangeStart', onHashChangeStart)
    }
  }, [router.events])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants