Skip to content

Instantly share code, notes, and snippets.

@reecelucas
Last active November 13, 2024 08:19
Show Gist options
  • Save reecelucas/2f510e6b8504008deaaa52732202d2da to your computer and use it in GitHub Desktop.
Save reecelucas/2f510e6b8504008deaaa52732202d2da to your computer and use it in GitHub Desktop.
React hook to enable/disable page scroll
import { useRef } from 'react';
const safeDocument = typeof document !== 'undefined' ? document : {};
/**
* Usage:
* const [blockScroll, allowScroll] = useScrollBlock();
*/
export default () => {
const scrollBlocked = useRef();
const html = safeDocument.documentElement;
const { body } = safeDocument;
const blockScroll = () => {
if (!body || !body.style || scrollBlocked.current) return;
const scrollBarWidth = window.innerWidth - html.clientWidth;
const bodyPaddingRight =
parseInt(window.getComputedStyle(body).getPropertyValue("padding-right")) || 0;
/**
* 1. Fixes a bug in iOS and desktop Safari whereby setting
* `overflow: hidden` on the html/body does not prevent scrolling.
* 2. Fixes a bug in desktop Safari where `overflowY` does not prevent
* scroll if an `overflow-x` style is also applied to the body.
*/
html.style.position = 'relative'; /* [1] */
html.style.overflow = 'hidden'; /* [2] */
body.style.position = 'relative'; /* [1] */
body.style.overflow = 'hidden'; /* [2] */
body.style.paddingRight = `${bodyPaddingRight + scrollBarWidth}px`;
scrollBlocked.current = true;
};
const allowScroll = () => {
if (!body || !body.style || !scrollBlocked.current) return;
html.style.position = '';
html.style.overflow = '';
body.style.position = '';
body.style.overflow = '';
body.style.paddingRight = '';
scrollBlocked.current = false;
};
return [blockScroll, allowScroll];
};
@ciruz
Copy link

ciruz commented May 15, 2024

thanks @litehacker for the TS version

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment