React useScrollLock Hook
React useScrollLock hook for scroll prevention. Lock document or element scrolling with layout shift prevention and automatic cleanup using TypeScript for Next.js.
Fighting with scroll prevention and layout shifts?
Join our Discord community for help from other developers.
Ever tried to prevent scrolling in React and ended up with overflow:hidden chaos, layout shift nightmares, or broken scrollbar compensation? You know the drill—manually setting document.body.style.overflow, forgetting to restore original styles, dealing with scrollbar width calculations, handling cleanup on unmount. This free open source React useScrollLock custom hook handles all that scroll prevention complexity so you can focus on building smooth modal experiences instead of debugging layout shift edge cases in your React applications.
useScrollLock showcase
Smart scroll locking with automatic layout shift prevention:
This free open source React hook simplifies scroll management with TypeScript support for modern JavaScript applications. Whether you're building modals, drawers, or overlay components in your Next.js projects, this React hook keeps your scroll locking reliable and visually stable.
Installation
npx shadcn@latest add https://www.shadcn.io/registry/use-scroll-lock.json
npx shadcn@latest add https://www.shadcn.io/registry/use-scroll-lock.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/use-scroll-lock.json
bunx shadcn@latest add https://www.shadcn.io/registry/use-scroll-lock.json
Why most scroll lock implementations suck
Look, you could keep manually setting overflow:hidden and dealing with the side effects. But then you hit the scroll lock complexity—layout shifts when scrollbars disappear, broken width calculations, forgotten style restoration, race conditions with multiple overlays in React applications.
Most developers manually set document.body.style.overflow = 'hidden' without compensating for scrollbar width, causing jarring layout shifts when content jumps in TypeScript components. Or they forget to restore original styles properly when unmounting, leaving users stuck with broken scroll states. Some handle multiple overlays incorrectly, creating race conditions where unlocking one modal breaks scroll for all others in Next.js projects.
This React hook uses optimized scroll management under the hood, with automatic scrollbar width compensation and proper style restoration in JavaScript applications. The browser handles all the overflow logic, plus you get comprehensive cleanup and layout shift prevention in one call.
Plus it handles all the edge cases—SSR compatibility with proper hydration, automatic style restoration, multiple target support, proper cleanup on unmount in React development. No more janky layout shifts or broken scroll states.
This free open source React hook manages scroll state while you focus on building features. Whether you're creating React applications, Next.js interfaces, or TypeScript components, reliable scroll locking keeps your JavaScript development smooth.
Features
- Automatic locking with smart component mount detection and default behavior in React applications
- Manual control providing optional lock/unlock functions for dynamic scenarios in TypeScript components
- Width reflow prevention preventing layout shift by compensating for scrollbar width in Next.js projects
- Custom targets supporting scroll lock on specific elements or document body in JavaScript development
- Style restoration restoring original styles automatically when unlocking for React frameworks
- SSR compatible safely handling server-side rendering without hydration issues in modern applications
- Free open source designed for modern React development workflows
When you'll actually use this
Real talk—this isn't for every scrolling scenario in React applications. CSS overflow controls handle basic scroll management perfectly. But when you need to prevent background scrolling without breaking your layout or causing visual jumps, this React hook delivers in Next.js projects.
Perfect for:
- Modal dialogs - Prevent background scrolling when overlays are active built with TypeScript
- Mobile navigation - Lock body scroll when slide-out menus are open using React patterns
- Lightbox galleries - Stop page scrolling during image/video viewing in JavaScript applications
- Form overlays - Prevent background interaction during multi-step processes in React components
- Loading screens - Lock scroll during full-screen loading states in Next.js applications
- Game interfaces - Prevent accidental scrolling during interactive gameplay using TypeScript safety
API Reference
useScrollLock
useScrollLock(options?: UseScrollLockOptions): UseScrollLockReturn
Parameter | Type | Default | Description |
---|---|---|---|
options | UseScrollLockOptions | {} | Configuration options for scroll locking behavior |
UseScrollLockOptions
Property | Type | Default | Description |
---|---|---|---|
autoLock | boolean | true | Whether to lock scroll automatically on component mount |
lockTarget | HTMLElement | string | document.body | Target element to lock (element or CSS selector) |
widthReflow | boolean | true | Whether to prevent width reflow by adding padding compensation |
UseScrollLockReturn
Property | Type | Description |
---|---|---|
isLocked | boolean | Current scroll lock state for conditional UI updates |
lock | () => void | Function to manually lock scroll on target element |
unlock | () => void | Function to manually unlock scroll and restore styles |
Common gotchas
Layout shift prevention requires calculation: The React hook measures scrollbar width and adds padding compensation to prevent content jumping when scrollbars hide in React applications. This calculation happens on mount and when locking, which may cause a brief delay on very slow devices.
Multiple components share scroll state: When multiple components use this React hook simultaneously, the last one to unlock restores the scroll state in TypeScript components. Plan your modal/overlay hierarchy carefully to avoid conflicts between nested or overlapping components.
Target elements must be scrollable: The hook only affects elements that actually have scrollbars in Next.js projects. Applying it to elements without overflow won't have any visible effect, but won't cause errors either.
SSR is handled automatically: The React hook safely does nothing on the server and activates after client hydration in JavaScript applications. No special configuration needed for Next.js or other SSR frameworks.
Scrollbar width varies by platform: Different operating systems have different scrollbar widths in React frameworks. The hook measures dynamically, but this can affect layout calculations on different devices.
Performance on slow devices: Scrollbar measurement and style application can be noticeable on very slow devices in TypeScript projects. Consider debouncing rapid lock/unlock operations for better performance.
Related hooks you will also like
useBoolean
Toggle state management for modal and overlay visibility
useIsMounted
Mount state checking for safe scroll lock cleanup
useEventListener
Event handling for escape key and modal dismissal patterns
useOnClickOutside
Outside click detection for modal and overlay dismissal
useWindowSize
Window dimensions for responsive modal and drawer behavior
useMediaQuery
Responsive breakpoints for mobile drawer vs desktop modal patterns
Questions you might have
React useScript Hook
React useScript hook for dynamic script loading. Load third-party libraries with status tracking, caching, and error handling using TypeScript for Next.js.
React useSessionStorage Hook
React useSessionStorage hook for session storage management. Persist temporary state across page reloads with automatic serialization using TypeScript for Next.js.