---
title: "How to Add Smooth Scroll to a Framer Site"
description: "Add smooth scroll to a Framer site the right way — the native toggle, a Lenis-based code override for full control, and the tradeoffs each brings."
canonical_url: "https://framerhub.io/blog/smooth-scroll-framer"
last_updated: "2027-01-20T00:00:00.000Z"
---

Smooth scroll — the inertia-heavy, slightly weighted feel of scrolling on a modern portfolio or agency site — is one of the easiest ways to make a Framer site feel more premium in the first three seconds, and one of the easiest to get subtly wrong. Framer actually ships a native option for this now, which surprises people who remember when it required custom code. Here's when to use the native toggle and when you actually need more control.

## The Native Option: Site Settings → Effects

Framer includes a built-in **Smooth Scrolling** toggle in your project's Site Settings, under the Effects tab. Turning it on applies momentum-based inertia scrolling across your entire site with zero code — the page continues to glide slightly after you stop scrolling, rather than stopping dead the instant your trackpad or wheel input ends.

This is the right choice for the majority of sites. It's zero-maintenance, works consistently across your whole project, and Framer keeps it updated as part of the platform rather than as a third-party dependency you're responsible for. If your only goal is "make scrolling feel less abrupt," stop here — you don't need custom code for this anymore.

This is worth stating plainly because a lot of older tutorials and forum threads still frame smooth scroll as something that always requires a third-party library and custom code in Framer. That was true a few versions ago; it isn't anymore. Before reaching for any code override, check your Site Settings first — you may already have what you need in a single toggle, and skipping straight to a custom implementation adds a dependency and a maintenance surface for a result the platform now offers natively.

## When the Native Toggle Isn't Enough

The native option is intentionally simple: one global feel, limited tuning. Reach for a code-based implementation when you need:

- **Custom easing or duration** tuned specifically to your site's pacing rather than Framer's default feel.
- **Scroll-linked animations synced to the smoothed position** — parallax layers, progress bars, or reveal animations that need to read the *smoothed* scroll value, not the raw browser scroll position, to stay visually in sync with what's on screen.
- **Per-section control**, such as disabling smooth scroll inside an embedded widget or a specific full-height section while keeping it active elsewhere.

If none of those apply to your project, the native toggle is genuinely the better choice — less code to maintain, no library to keep updated, no edge cases to debug.

## Building It With Lenis (Code Override)

[Lenis](https://github.com/darkroomengineering/lenis) is the most widely used smooth scroll library in modern web design specifically because it's lightweight and plays well with scroll-linked animation libraries. Here's a working setup as a Framer code override applied to your page.

```jsx
import { useEffect } from "react"
import Lenis from "lenis"

export function withSmoothScroll(Component): ComponentType {
  return (props) => {
    useEffect(() => {
      const lenis = new Lenis({
        duration: 1.1,
        easing: (t) => 1 - Math.pow(1 - t, 3),
        smoothWheel: true,
        wheelMultiplier: 1,
      })

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

      return () => lenis.destroy()
    }, [])

    return <Component {...props} />
  }
}
```

Apply this override to your page's top-level frame (or root layout component) rather than a single section — Lenis needs to control the whole page's scroll behavior to work correctly, so applying it to a nested element produces inconsistent results.

### Syncing Other Animations to Lenis

The real payoff of the code approach is syncing other scroll-driven effects to Lenis's smoothed scroll value instead of the browser's raw scroll position, so a parallax layer or reveal animation stays visually aligned with what the visitor is actually seeing mid-scroll rather than reacting to input that's already been smoothed away:

```jsx
lenis.on("scroll", ({ scroll, progress }) => {
  // scroll = current smoothed scroll position in px
  // progress = 0 to 1 across the full scrollable height
  // drive your own motion values from these instead of window.scrollY
})
```

Any scroll-linked animation on the page — parallax backgrounds, progress indicators, reveal-on-scroll sections — should read from this `scroll` event rather than `window.scrollY` once Lenis is active, or the two systems will visibly disagree with each other during fast scrolling.

## Performance Tradeoffs You Should Actually Know

Smooth scroll libraries intercept and recalculate scroll position on every animation frame, which is a real, continuous cost — not free, even when implemented well. On a page that's already animation-heavy (multiple scroll-triggered reveals, video backgrounds, complex gradients), stacking a smooth scroll library on top compounds the total frame budget the browser has to hit 60fps. Test on a mid-range device and a throttled CPU in dev tools, not just your development machine, before shipping — a smooth scroll implementation that feels flawless on a high-end laptop can visibly stutter on the hardware a meaningful share of your visitors are actually using. Our [performance optimization guide](/blog/optimize-framer-site-performance) covers the broader set of levers for keeping a Framer site fast, which is worth reading alongside this if smooth scroll is one of several animation-heavy features on the page.

## Accessibility: The Part Most Implementations Skip

Smoothed scrolling changes how the browser's native scroll behaves, and a careless implementation can break things that have nothing to do with visual polish:

- **Keyboard scrolling (Page Down, spacebar, arrow keys)** needs to keep working — test this explicitly, since some naive smooth scroll implementations intercept scroll events in a way that breaks keyboard-driven scrolling entirely.
- **Browser find-in-page (Cmd/Ctrl+F)** should still be able to scroll to and highlight matched text — heavily customized scroll interception can interfere with this.
- **prefers-reduced-motion** should disable or significantly reduce the smoothing effect for visitors who've set that OS-level preference — wrap the Lenis initialization in a check for this media query and skip it (or use a much shorter duration) when set.

Lenis handles keyboard and find-in-page correctly out of the box in most configurations, which is part of why it's become the default choice over older, more invasive smooth scroll approaches — but it's still worth explicitly testing rather than assuming.

## Common Mistakes When Adding Smooth Scroll

- **Applying the Lenis override to a nested section instead of the page root.** Smooth scroll needs to own the whole document's scroll behavior. Applied to a single frame partway down the layer tree, you'll typically get either no effect or conflicting scroll behavior between the smoothed section and the rest of the page.
- **Leaving the raf loop running after the component unmounts.** The cleanup function in the snippet above (`return () => lenis.destroy()`) matters — skip it and you leave a dangling animation frame loop running, which is a real, if subtle, source of performance degradation on long sessions or single-page-app-style navigation.
- **Mixing native smooth scroll and a code library simultaneously.** Turning on Framer's native toggle while also running a Lenis override stacks two competing scroll-smoothing systems, which typically produces a stuttery, fighting-itself feel rather than a smoother one. Pick one.
- **Tuning duration and easing without testing on an actual trackpad and an actual mouse wheel.** These two input methods produce meaningfully different raw scroll deltas, and a duration/easing combination tuned only against one can feel wrong on the other.

## Testing Checklist Before Shipping

Before considering a smooth scroll implementation done, verify each of the following, since a good visual first impression can hide problems that only surface in real use:

- Keyboard scrolling (Page Down, spacebar, arrow keys) still works correctly
- Anchor links and in-page navigation animate to the correct target position
- The effect performs acceptably on a throttled/mid-range device profile, not just your dev machine
- `prefers-reduced-motion` visitors get a reduced or disabled effect
- Any scroll-linked animations elsewhere on the page (parallax, reveals, progress bars) stay visually in sync rather than drifting out of alignment during fast scrolling

## Smooth Scroll and Horizontal Scroll Sections

If your site also includes a horizontal-scrolling section — a project showcase or gallery that scrolls sideways as the visitor scrolls down — the interaction between vertical smooth scroll and horizontal scroll-jacking needs deliberate handling, since both systems are competing to interpret the same scroll input. Our [Framer horizontal scroll guide](/blog/framer-horizontal-scroll-guide) covers that specific combination in depth if it applies to your project.

## Choosing Your Approach

<table>
<thead>
  <tr>
    <th>
      Need
    </th>
    
    <th>
      Recommendation
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Just want scrolling to feel less abrupt
    </td>
    
    <td>
      Native Smooth Scrolling toggle
    </td>
  </tr>
  
  <tr>
    <td>
      Need custom easing/duration tuned to brand feel
    </td>
    
    <td>
      Lenis code override
    </td>
  </tr>
  
  <tr>
    <td>
      Have scroll-linked animations (parallax, reveals)
    </td>
    
    <td>
      Lenis code override, synced
    </td>
  </tr>
  
  <tr>
    <td>
      Site is already animation-heavy
    </td>
    
    <td>
      Test performance carefully either way; consider native first
    </td>
  </tr>
  
  <tr>
    <td>
      Have a horizontal scroll section
    </td>
    
    <td>
      Lenis, with explicit handling for the horizontal section
    </td>
  </tr>
</tbody>
</table>

For most marketing sites, start with the native toggle. Move to a code implementation only once you have a concrete reason the native option can't deliver — smooth scroll is a feature where "more sophisticated" isn't automatically "better," and unnecessary custom code is one more thing to maintain and one more performance cost to carry. If you're building out other interactive, code-driven sections alongside this, FramerHub's [component library](/components) and the [Components plugin](/plugins/framer-components) are worth a look before hand-building everything from scratch.

## FAQ

**Does Framer have smooth scroll built in?**
Yes — Framer's Site Settings has a native Smooth Scrolling toggle under Effects that adds momentum-based inertia to scrolling with no code required. It's a real, working option for most sites.

**Why would I need a code override if native smooth scroll exists?**
The native toggle applies one global feel with limited tuning. A code-based approach (typically using the Lenis library) gives you control over easing curves, duration, and lets you sync other scroll-linked animations to the same smoothed scroll position — something the native toggle doesn't expose.

**Does smooth scroll hurt SEO or accessibility?**
It can hurt accessibility if it isn't implemented carefully — smoothed scrolling can interfere with keyboard scrolling, screen reader navigation, and browser find-in-page behavior if the underlying implementation intercepts native scroll events too aggressively. It has no direct SEO impact since it's a visual/interaction layer, not a content change.

**Will smooth scroll slow down my site?**
A well-implemented smooth scroll library has a small but real performance cost, since it's intercepting and recalculating scroll position continuously. On a content-heavy or animation-heavy page, that cost compounds — test on a mid-range device, not just your development machine.

**Should smooth scroll be on or off for anchor links and in-page navigation?**
Keep it on — most smooth scroll libraries, including Lenis, handle anchor link jumps by animating to the target smoothly rather than snapping instantly, which is usually a UX improvement rather than a conflict.
