# useBodyOverflow

Locks page scroll by toggling overflow-hidden on document.body.

## Installation

```bash
npx shadcn@latest add https://reactdocs.canceydejean.dev/r/use-body-overflow.json
```

[Registry JSON](https://reactdocs.canceydejean.dev/r/use-body-overflow.json)

## Preview

```tsx
import { useState } from "react";

import { Button } from "@/components/ui/button";

import { useBodyOverflow } from "@/hooks/use-body-overflow";

export function Preview() {
  const [isOpen, setIsOpen] = useState(false);

  useBodyOverflow(isOpen);

  return (
    <div className="flex flex-col items-center gap-3 text-center">
      <Button onClick={() => setIsOpen((open) => !open)}>
        {isOpen ? "Unlock page scroll" : "Lock page scroll"}
      </Button>
      <p className="text-sm text-muted-foreground">
        {isOpen ? "Body scroll is locked. Try scrolling the page." : "Body scroll is unlocked."}
      </p>
    </div>
  );
}
```


## Source

### hooks/use-body-overflow.ts

```ts
"use client";
import { useEffect } from "react";

export const useBodyOverflow = (isOpen: boolean) => {
  useEffect(() => {
    if (isOpen) {
      document.body.classList.add("overflow-hidden");
    } else {
      document.body.classList.remove("overflow-hidden");
    }

    // Cleanup function
    return () => {
      document.body.classList.remove("overflow-hidden");
    };
  }, [isOpen]);
};
```



## Usage

Pass `true` while a modal, sheet, drawer, or mobile menu is open. The hook adds `overflow-hidden` to
`document.body` and removes it when closed or on unmount.

```tsx
import { useBodyOverflow } from "@/hooks/use-body-overflow";

export function MobileMenu({ open }: { open: boolean }) {
  useBodyOverflow(open);

  return open ? <nav>{/* overlay content */}</nav> : null;
}
```

Use alongside overlay components so background content cannot scroll while the overlay is visible.

