Smooth scroll doesn't work with Lenis when link with id clicked

1.7k Views Asked by At

Do you know why scroll-behavior: smooth doesn't work with Lenis library of smooth -scrolling? When I comment the Lenis code below it works fine. When I add the Lenis code it doesn't scroll smoothly when I click the tag with id.

const lenis = new Lenis({
  duration: 2.5
})

function raf(time) {
  lenis.raf(time)
  requestAnimationFrame(raf)
}
requestAnimationFrame(raf)

lenis.on('scroll', ScrollTrigger.update)

gsap.ticker.add((time) => {
  lenis.raf(time * 1000)
})
html {
  scroll-behavior: smooth;
}
 <h2><a class="c-btn" href="#pages-main">scroll down</a></h2>
 
  <section id="pages-main"></section>

Do you know why scroll-behavior: smooth doesn't work with Lenis library of smooth -scrolling? When I comment the Lenis code below it works fine. When I add the Lenis code it doesn't scroll smoothly when I click the tag with id.

const lenis = new Lenis({
  duration: 2.5
})

function raf(time) {
  lenis.raf(time)
  requestAnimationFrame(raf)
}
requestAnimationFrame(raf)

lenis.on('scroll', ScrollTrigger.update)

gsap.ticker.add((time) => {
  lenis.raf(time * 1000)
})
html {
  scroll-behavior: smooth;
}
 <h2><a class="c-btn" href="#pages-main">scroll down</a></h2>
 
  <section id="pages-main"></section>

2

There are 2 best solutions below

0
Abhrajit Ray On
import { LenisInstance, ScrollToParams, useLenis } from "@studio-freight/react-lenis";

// Using the useLenis hook to get a LenisInstance
  const lenisInstance: LenisInstance = useLenis();

  // Function for smooth scrolling
    const handleClick = (targetElement: string | number | HTMLElement)=>{

    if (targetElement) {
      const scrollToOptions: ScrollToParams = {
        // Customize scroll options if needed
        offset: 0,
        lerp: 0.1,
        duration: 1.5,
        easing: (rawValue: number) => rawValue, // Example easing function
        immediate: false,
        lock: false,
        force: false,
      };

      lenisInstance.scrollTo(targetElement, scrollToOptions);
    }
  }

I have used react-lenis for this but it should probably work with the normal lenis package as well.

0
Rohit Kaushal On

Setting scroll-behavior: smooth on html will fix the scrolling on # links. BUT now the normal scrolling will get stuck. Apparently, lenis scroll works by taking control of the scroll on the html element and it doesn't keep it on smooth scroll to achieve the effect manually by javascript.

My solution for this was to write this fix along with the lenis initialization code -

// fix for id links
document.querySelectorAll('a[href^="#"]').forEach((el) => {
  el.addEventListener('click', (e) => {
    e.preventDefault()
    const id = el.getAttribute('href')?.slice(1)
    if (!id) return
    const target = document.getElementById(id)
    if (target) {
      target.scrollIntoView({ behavior: 'smooth' })
    }
  })
})

the only problem with this is that it won't update the url with #id if you try doing that with document.location.hash = "#id", it will again fallback to the default instant scroll.