Vize

Scroll Lock

Headless Scroll Lock; covers React Aria usePreventScroll, Radix RemoveScroll.

Package @vizejs/ui/scroll-lock
Maturity stable
Own the source vize lib pull scroll-lock
Requires —
Aliases body scroll lock, document scroll lock, overlay scroll lock
Covers React Aria usePreventScroll, Radix RemoveScroll

API

createScrollLock

Lock a reactive document viewport without suppressing browser zoom gestures.

function createScrollLock(options: ScrollLockOptions): ScrollLockController

useScrollLock

Create, mount-activate, and scope-dispose a document scroll lock.

function useScrollLock(options: ScrollLockOptions): ScrollLockController

captureDocumentLock

function captureDocumentLock(document: Document): DocumentLockSnapshot | null

measureScrollbarGap

function measureScrollbarGap(document: Document): number

resolveScrollLockStrategy

function resolveScrollLockStrategy( document: Document, strategy: ScrollLockStrategy, ): Exclude<ScrollLockStrategy, "auto">

applyDocumentLock

function applyDocumentLock( snapshot: DocumentLockSnapshot, strategy: Exclude<ScrollLockStrategy, "auto">, gap: number, preserveGap: boolean, ): void

restoreDocumentLock

function restoreDocumentLock(snapshot: DocumentLockSnapshot): void

restoreDocumentScroll

function restoreDocumentScroll(snapshot: DocumentLockSnapshot): void

readDocument

function readDocument(source: unknown): Document | null

readBoolean

function readBoolean(source: unknown, name: string, fallback: boolean): boolean

readStrategy

function readStrategy(source: unknown): ScrollLockStrategy

validateScrollLockOptions

function validateScrollLockOptions(options: ScrollLockOptions): void

recomputeScrollLock

function recomputeScrollLock(state: DocumentLockState): void

attachScrollLock

function attachScrollLock(token: ScrollLockToken, document: Document): void

detachScrollLock

function detachScrollLock(token: ScrollLockToken): void

refreshScrollLock

function refreshScrollLock(token: ScrollLockToken): void

Behavior

createScrollLock freezes one document's layout viewport while leaving focus, outside inerting, dismissal, visual styling, and overlay semantics to independently composable primitives.

Concern Contract
Ownership Document locks are reference-counted; the document restores only after its final enabled owner exits.
Strategy overflow locks the root scroll container; fixed also fixes the body; auto selects fixed positioning only for iOS-like touch platforms.
Composition A nested fixed owner upgrades the whole stack and releasing it returns atomically to overflow locking without exposing an unlocked frame.
Restoration Owned inline values, priorities, the data attribute, and the captured layout-viewport offset restore exactly.
Scrollbar gap Root scrollbar-gutter: stable preserves classic gutters where supported; a measured logical-padding fallback and CSS custom property are exposed.
Direction Gap fallback uses padding-inline-end; native gutters remain user-agent positioned for platform and bidirectional conventions.
Zoom No touch-action or gesture cancellation is installed, so page zoom and visual-viewport panning remain browser controlled.
Viewports Scroll capture uses layout-viewport scrollX/scrollY; pinch zoom and virtual keyboards may independently move or resize the visual viewport.
Documents Reactive migration restores the old document before acquiring the new document; iframe documents keep independent stacks.
Server rendering Setup performs no global DOM access; a nullable document joins the stack only after hydration mount.
Vapor A public composable fixture must compile without diagnostics in native DOM, SSR, and Vapor lanes.
Styling The package emits no CSS; [data-vize-scroll-locked] and --vize-scroll-lock-scrollbar-gap are explicit user styling hooks.
Tree shaking Root and subpath consumers emit identical JavaScript, retain no unrelated families, and emit zero CSS.

The root-element gutter behavior follows CSS Overflow Level 3. Layout and visual viewport coordinates follow CSSOM View. The primitive deliberately does not suppress Pointer Events touch-action behaviors because disabling pan and pinch gestures would also disable user zoom.