How to Make Site Scrolling Truly Smooth Without Breaking Accessibility
Have you ever visited a site where scrolling feels "syrupy" or, conversely, too jarring? Designers love smooth scroll because it adds polish and a premium feel to the interface. But for developers, it often turns into a nightmare: standard smooth scroll libraries frequently break native navigation, conflict with position: sticky, or make the browser suffer from low frame rates.
Recently I came across Lenis from the darkroom.engineering team. These folks approached the problem differently: instead of completely replacing browser behavior, they created a lightweight layer that works on top of native scrolling.
What's the Main Problem with Regular Libraries
Most smooth scroll tools simply "disable" standard scrolling and try to mimic it through transforms (CSS transforms). This causes things like keyboard focus, page search (Cmd+F), and screen reader functionality to break.
Lenis (from Latin — "smooth") preserves native scrolling. This means your anchor links will work, and the browser will still understand exactly where the user is on the page. Plus, the library is only a few kilobytes and doesn't drag along a mountain of dependencies.
What Lenis Can Do
The library tackles several frontend developer pain points at once.
Synchronization with WebGL and Animations
If you're building complex parallax effects or tying scroll to canvas (WebGL), you need a single source of truth for scroll position. Lenis plays perfectly with GSAP ScrollTrigger. In my experience, this is the most stable way to avoid elements "jittering" during fast scrolling.
Working with Any Axes
You can configure smoothness for vertical, horizontal, or even nested scrolling. The latter is especially nice: often you need the main page to scroll smoothly while some modal block inside lives its own life.
Framework Support
Though I prefer vanilla JS for things like this, the project has official adapters for React, Vue, and even Framer. This saves time on passing refs and component lifecycle management.
How to Get Started
Installation is standard:
npm i lenis
Basic initialization is as simple as it gets. You can enable automatic animation loop (autoRaf) so you don't have to mess with requestAnimationFrame manually:
import Lenis from 'lenis'
import 'lenis/dist/lenis.css'
const lenis = new Lenis({
autoRaf: true,
});
// Можно подписаться на события, если нужно обновлять свои анимации
lenis.on('scroll', (e) => {
console.log('Текущая позиция:', e.scroll);
});
If you're using GSAP (and for cool sites, it's the de facto standard), integration will be a bit more complex, but more reliable:
const lenis = new Lenis();
lenis.on('scroll', ScrollTrigger.update);
gsap.ticker.add((time) => {
lenis.raf(time * 1000);
});
gsap.ticker.lagSmoothing(0);
Fine Points and Limitations
Despite how cool it is, Lenis has its quirks. For example, in Safari, frame rate updates may be capped at 60 FPS (or even 30 FPS in low power mode), which can sometimes be noticeable on high refresh rate monitors.
Another thing — iframe. Scrolling inside iframes won't be smooth, as they don't bubble mouse wheel events outward. This is a browser security restriction, and the library can't do anything about it.
If you have elements on your page that should scroll normally (like a text field or dropdown), use the data-lenis-prevent attribute. This will save you from strange interface behavior.
Is It Worth Implementing
If you're building a landing page, portfolio, or promo site where aesthetics matter — definitely yes. Lenis gives you that "expensive" effect without compromising accessibility.
For heavy dashboards or admin panels with tons of tables, I'd probably hold off. There, an extra abstraction layer over scrolling can only get in the way of users quickly navigating through data.
Overall, it's one of the cleanest and most performant tools in its class today. Check out their Showcase — it has truly impressive examples of how ordinary scrolling becomes part of visual storytelling.
Related projects