lockUnlockBodyScroll
Toggles body scroll lock. When locked, sets overflow:hidden and compensates for scrollbar width.
1/**
2 * Toggles body scroll lock.
3 * When locked, sets overflow:hidden and compensates for scrollbar width.
4 */
5export function toggleBodyScroll(): void {
6 const body = document.body;
7 const isLocked = body.style.overflow === 'hidden';
8
9 if (isLocked) {
10 body.style.overflow = '';
11 body.style.paddingRight = '';
12 } else {
13 const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
14 body.style.overflow = 'hidden';
15 body.style.paddingRight = `${scrollbarWidth}px`;
16 }
17}
Prevents Layout Shift
Adds
padding-right
equal to scrollbar width when scroll is locked, avoiding content jump due to scrollbar disappearance.Simple Toggle Logic
Provides a single, reusable function to both lock and unlock scroll with minimal code and clear state detection.
Native Scroll Lock
Relies on native
overflow: hidden
CSS behavior, ensuring wide compatibility across modern browsers.No External Dependencies
Fully self-contained utility that doesn't require third-party libraries or complex setup.
Tests | Examples
1test('toggleBodyScroll locks body scroll when not locked', () => {
2 document.body.style.overflow = '';
3 document.body.style.paddingRight = '';
4
5 const initialWidth = window.innerWidth;
6 Object.defineProperty(document.documentElement, 'clientWidth', {
7 configurable: true,
8 value: initialWidth - 20,
9 });
10
11 toggleBodyScroll();
12
13 expect(document.body.style.overflow).toBe('hidden');
14 expect(document.body.style.paddingRight).toBe('20px');
15
16 // Restore
17 Object.defineProperty(document.documentElement, 'clientWidth', {
18 configurable: true,
19 value: initialWidth,
20 });
21});
22
23test('toggleBodyScroll unlocks body scroll when already locked', () => {
24 document.body.style.overflow = 'hidden';
25 document.body.style.paddingRight = '20px';
26
27 toggleBodyScroll();
28
29 expect(document.body.style.overflow).toBe('');
30 expect(document.body.style.paddingRight).toBe('');
31});
Common Use Cases
Modal or Dialog Handling
Lock background scroll when modals, lightboxes, or side drawers are open.
Mobile Navigation Drawers
Prevent body scrolling when a mobile menu or full-screen overlay is active.
Focus-Driven Experiences
Create immersive flows by disabling background interaction during onboarding steps or alerts.
Prevent Scroll During Transitions
Temporarily block scroll during animations or transitions that affect layout or user flow.