
This script controls when page scrolling is active or inactive using Lenis. Scrolling can be paused, resumed, or toggled based on UI state such as lightboxes or popups, or through simple attributes.
Copy & paste the scripts before the </body> tag of your project. If you added them before for another setup, skip this step.
Place the code in an HTML widget or add it through Elementor → Custom Code (before the closing </body> tag) either globally or only on selected pages.
Paste the code through the page or site settings, or add it via Elementor → Custom Code (before </body>) for broader use.
Paste the script through Elementor → Custom Code (set to load after </body>) for site-wide or page-specific loading.
document.addEventListener("DOMContentLoaded", () => {
const lenis = window.ouLenis;
if (!lenis) return;
// --- CONFIG --- //
const config = {
lightbox: true,
scrollbarShift: true
};
// --- ATTRIBUTES --- //
const ATTR = {
start: '[ou-lenisdisable-scroll="start"]',
stop: '[ou-lenisdisable-scroll="stop"]',
toggle: '[ou-lenisdisable-scroll="toggle"]',
visible: '[ou-lenisdisable-scroll="visible"]',
offcanvas: '[ou-lenisdisable-scroll="offcanvas"]'
};
// --- SCROLLBAR --- //
const getScrollbarWidth = () =>
window.innerWidth - document.documentElement.clientWidth;
const applyScrollbarFix = active => {
if (!config.scrollbarShift) return;
document.body.style.paddingRight = active
? `${getScrollbarWidth()}px`
: "";
};
const originalStart = lenis.start.bind(lenis);
const originalStop = lenis.stop.bind(lenis);
lenis.start = () => {
applyScrollbarFix(false);
originalStart();
};
lenis.stop = () => {
applyScrollbarFix(true);
originalStop();
};
// --- STATE CONTROLS --- //
document.addEventListener("click", e => {
if (e.target.closest(ATTR.start)) lenis.start();
if (e.target.closest(ATTR.stop)) lenis.stop();
if (e.target.closest(ATTR.toggle)) {
lenis.isStopped ? lenis.start() : lenis.stop();
}
});
// --- VISIBLE --- //
const io = new IntersectionObserver(entries => {
entries.forEach(entry => {
entry.isIntersecting ? lenis.stop() : lenis.start();
});
});
document
.querySelectorAll(ATTR.visible)
.forEach(el => io.observe(el));
// --- OFFCANVAS --- //
document
.querySelectorAll(ATTR.offcanvas)
.forEach(el => {
const parent = el.closest(".e-off-canvas");
if (!parent) return;
const mo = new MutationObserver(() => {
const open = parent.getAttribute("aria-hidden") === "false";
open ? lenis.stop() : lenis.start();
});
mo.observe(parent, {
attributes: true,
attributeFilter: ["aria-hidden"]
});
});
// --- LIGHTBOX --- //
if (config.lightbox) {
const lightboxObserver = new MutationObserver(() => {
const popup = document.querySelector(".elementor-lightbox");
if (!popup) return;
const visible = popup.style.display !== "none";
visible ? lenis.stop() : lenis.start();
});
lightboxObserver.observe(document.body, {
subtree: true,
attributes: true,
attributeFilter: ["style", "class"]
});
}
});Place the PHP snippet inside your theme’s functions.php or using any code snippet to enable logic.
Use these attributes to manage how scrolling works in your project.
Add data-lenis-stop attribute to any button, link, or element to immediately pause scrolling. Once clicked, the page will freeze and background movement will stop completely.
Use data-lenis-start on another element, such as a close button or continue button, to resume scrolling after it has been paused.
Use data-lenis-toggle if you want a single button to handle both states. Clicking the element will switch between pausing and resuming scroll automatically. If scrolling is active, it pauses. If scrolling is already paused, it turns back on.
Add data-lenis-visible to any element to automatically pause scrolling when it appears on screen and resume when it leaves. This works great for popups, full screen sections, or important content that should hold focus.
For Elementor popups, just add the same attribute to the popup container. Scrolling will stop when it opens and continue when it closes.
Add data-lenis-visible-offcanvas to a wrapper inside the off-canvas panel, not the button that opens it. You can place it on any inner container within the panel content.
The script will automatically detect when the panel opens and closes, pause scrolling while it is open, and restore scrolling when it closes.
These options control how scrolling reacts to UI elements like lightbox and layout shifts.
The lightbox setting controls whether Elementor lightboxes automatically pause scrolling. When enabled, the page freezes while the lightbox is open and resumes once it closes.
The scrollbarShift setting controls whether the page should compensate for the browser scrollbar when scrolling is paused.
Without this, the page may “jump” horizontally because the scrollbar appears or disappears when Lenis stops scrolling.
When enabled, the script adds a small padding to the body to keep the layout perfectly stable.
Some solutions only work on the live site. Always publish and test after each change, as results may not appear in the editor.