Skip to content

Instantly share code, notes, and snippets.

@pedroalmeida415
Forked from reecelucas/useScrollBlock.js
Created April 14, 2022 19:03
Show Gist options
  • Save pedroalmeida415/cd9a985f86f198a727f7214963d7aa95 to your computer and use it in GitHub Desktop.
Save pedroalmeida415/cd9a985f86f198a727f7214963d7aa95 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];
};
@pedroalmeida415
Copy link
Author

Typescript:

`import { useRef } from 'react';

const useScrollBlock = () => {
const scroll = useRef(false);

const blockScroll = () => {
if (typeof document === 'undefined') return;

const html = document.documentElement;
const { body } = document;

if (!body || !body.style || scroll.current) return;

const scrollBarWidth = window.innerWidth - html.clientWidth;
const bodyPaddingRight =
  Number(window.getComputedStyle(body).getPropertyValue('padding-right')) ||
  0;

html.style.position = 'relative'; 
body.style.position = 'relative'; 
html.style.overflow = 'hidden'; 
body.style.overflow = 'hidden'; 
body.style.paddingRight = `${bodyPaddingRight + scrollBarWidth}px`;

scroll.current = true;

};

const allowScroll = () => {
if (typeof document === 'undefined') return;

const html = document.documentElement;
const { body } = document;

if (!body || !body.style || !scroll.current) return;

html.style.position = '';
html.style.overflow = '';
body.style.position = '';
body.style.overflow = '';
body.style.paddingRight = '';

scroll.current = false;

};

return [blockScroll, allowScroll];
};

export { useScrollBlock };`

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