Search code examples
anchorsveltepage.js

anchor link in Svelte app using page.js routing


I have an anchor tag on a page in my Svelte app. The link to the anchor works on the page itself, but I can't link to the anchor from another page. And when I enter the URL with the anchor, the page doesn't scroll down. I need to be able to give people a link and have them go to a specific part of the page.

Here's the relevant code:

    <script>
      function scrollIntoView({ target }) {
        const el = document.querySelector(target.getAttribute("href"));
        if (!el) return;
        el.scrollIntoView({
          behavior: "smooth",
        });
      }
    </script>

    <nav>
      <a href="#here" on:click|preventDefault={scrollIntoView}>go to anchor</a>
    </nav>

    <main>
      <section id="section-1">
        ... lots of lorem ipsum ...
      </section>
      <section>
        <h2 id="here">anchor</h2>

And I have a REPL here: https://svelte.dev/repl/e651218bdb47455d9cafe8bff27c8d7b?version=3.24.0

I'm using page.js for my routing to components -- I haven't found anything specific about targeting anchor tags in the documentation.

Any help would be greatly appreciated.


Solution

  • You don't need JS for smooth scrolling, just add some CSS:

    /* :global if in component */
    :global(html) {
        scroll-behavior: smooth;
    }
    

    REPL

    As for scroll on page load, that is an issue of client-side rendering. For SSR the CSS alone takes care of everything but if the element that should be scrolled to is added after the page is loaded, the scroll will not happen.

    One way of dealing with that would be to add an onMount, ideally high up in the component hierarchy so it triggers after everything is mounted, which manually performs the scroll:

    onMount(() => {
      const { hash } = document.location;
      const scrollTo = hash && document.getElementById(hash.slice(1));
      if (scrollTo)
        scrollTo.scrollIntoView();
    });
    

    (Some of that logic is from SvelteKit which does all that automatically.)