Accessible Smooth Scrolling
Using Lenis Smooth Scroll to create accessible smooth scrolling
Whether you like it or not, smooth scrolling is something you can find on almost every Awwward-winning website. There are various methods to accomplish this task. One such way is by using tools like GSAP or Locomotive Scroll. My preferred way is with Studio Lenis' Smooth scroll package. Many libraries tend to interfere with the user's natural scrolling behavior. However, Lenis' library doesn't interfere with the user's native scroll. Instead, it applies a smooth or gradual transition to the native scroll while providing the correct scroll position to any software or code that requires it.
For this tutorial, we will be using the Next.JS framework. Next.js simplifies building React websites. It helps them load faster for visitors, which improves user experience. It also benefits search engines, making your site more discoverable. Overall, Next.js saves you time coding and gets your website running smoothly.
Setting up the project
Let's start by creating a new Next.js project. You can do this by running the following command in your terminal:
1bun create-next-app
This automatically installs dependencies using npm. You can use the following link as a reference: https://bun.sh/guides/ecosystem/nextjs.
Adding Lenis to your project
To install the package, run the following command:
1bun add @studio-freight/lenis
1const lenis = new Lenis();23lenis.on("scroll", (e) => {4 console.log(e);5});67function raf(time) {8 lenis.raf(time);9 requestAnimationFrame(raf);10}1112requestAnimationFrame(raf);
We will need to add some syntax. Import the following at the top of your file:
1import Lenis from '@studio-freight/lenis'
For our code to work as intended, we want to place the logic inside the useLayoutEffect
hook. This hook is called before the user can see any changes in the render, while the useEffect
hook gets called after the user can see the changes. The goal is to execute the code inside the effect immediately before the browser paints the DOM; to ensure the user experiences smooth scrolling from the start. That's why we choose to use the useLayoutEffect
hook. Since we want the logic to pass to the whole site, we want to add a children
property with a ReactNode
as its typing. The final result should look something like this:
1"use client";2import { useLayoutEffect, useRef } from "react";3import Lenis from "@studio-freight/lenis";45interface SmoothScrollProps {6 children: React.ReactNode;7}89const SmoothScrollWrapper: React.FC<SmoothScrollProps> = ({ children }) => {10 const lenisRef = (useRef < Lenis) | (null > null);1112 useLayoutEffect(() => {13 lenisRef.current = new Lenis();1415 function raf(time: number) {16 if (lenisRef.current) {17 lenisRef.current.raf(time);18 }19 requestAnimationFrame(raf);20 }2122 requestAnimationFrame(raf);23 }, []);2425 return <>{children}</>;26};2728export default SmoothScrollWrapper;
Also, do not forget to put 'use client'
at the top of your file. Next.js will throw an error otherwise because we use the UseRef hook.
Finishing touches
While not mandatory, I recommend adding the following styling properties to your global.css file. These changes optimize native browser functions to enhance performance and efficiency, ensuring smoother operation in various scenarios.
1html.lenis,2html.lenis body {3 height: auto;4}56.lenis.lenis-smooth {7 scroll-behavior: auto !important;8}910.lenis.lenis-smooth [data-lenis-prevent] {11 overscroll-behavior: contain;12}1314.lenis.lenis-stopped {15 overflow: hidden;16}1718.lenis.lenis-scrolling iframe {19 pointer-events: none;20}
When the component is created you can use it in your layout file as follows:
1export default function RootLayout({2 children,3}: Readonly<{4 children: React.ReactNode,5}>) {6 return (7 <html lang="en">8 <SmoothScrollWrapper>9 <body className={inter.className}>{children}</body>10 </SmoothScrollWrapper>11 </html>12 );13}
Well, look at that, already Awwwards ready! If you have any questions, feel free to contact me. Or take a look at the source code for this project!
Darkroom Engineering created Lenis.
Cheers,
Fabrice