import inline from '../../assets/detectOverflow.inline.jpg';

# detectOverflow

A utility function that computes the overflow offsets of either
the reference or floating element relative to any clipping
boundaries.

<CircleImage name="detectOverflow" inline={inline} />

A clipping boundary is one that causes child elements inside it
to be clipped if they overflow it.

Visibility optimizer middleware use this function for **collision
detection**, making it useful for your own custom middleware that
perform visibility optimization.

## Usage

Inside your custom middleware, make your `fn{:.function}`
`async{:.keyword}` and `await{:js}` it, passing in the middleware
`state{:.param}`:

```js
import {detectOverflow} from '@floating-ui/dom';

const middleware = {
  name: 'middleware',
  async fn(state) {
    const overflow = await detectOverflow(state);
    return {};
  },
};
```

The returned value, `overflow{:.const}`, is a
`SideObject{:.class}` containing side properties with numbers
representing offsets.

- A positive number means the element is overflowing the clipping
  boundary by that number of pixels.
- A negative number means the element has that number of pixels
  left before it will overflow the clipping boundary.
- `0{:js}` means the side lies flush with the clipping boundary.

## Options

`detectOverflow(){:js}` takes options as a second argument.

```js
await detectOverflow(state, {
  // options
});
```

### boundary

```ts
type Boundary =
  | 'clippingAncestors'
  | Element
  | Array<Element>
  | Rect;
```

This describes the clipping element(s) or area that overflow will
be checked relative to. The default is
`'clippingAncestors'{:js}`, which are the overflow ancestors
which will cause the element to be clipped.

```js
await detectOverflow(state, {
  boundary: document.querySelector('#container'),
});
```

### rootBoundary

```ts
type RootBoundary = 'viewport' | 'document' | Rect;
```

This describes the root boundary that the element will be checked
for overflow relative to. The default is `'viewport'{:js}`, which
is the area of the page the user can see on the screen. This is
the
[Visual Viewport](https://developer.mozilla.org/en-US/docs/Web/API/Visual_Viewport_API)
which correctly handles pinch-zooming and mobile viewports when
the keyboard is open.

The other string option is `'document'{:js}`, which is the entire
page outside the viewport.

```js
await detectOverflow(state, {
  rootBoundary: 'document', // 'viewport' by default
});
```

You may also pass a `Rect{:.class}` object to define a custom
boundary area (relative to the viewport).

```js
await detectOverflow(state, {
  // Layout viewport, instead of the visual viewport
  rootBoundary: {
    x: 0,
    y: 0,
    width: document.documentElement.clientWidth,
    height: document.documentElement.clientHeight,
  },
});
```

### padding

```ts
type Padding =
  | number
  | Partial<{
      top: number;
      right: number;
      bottom: number;
      left: number;
    }>;
```

This describes the virtual padding around the boundary to check
for overflow.

```js
await detectOverflow(state, {
  // 5px on all sides
  padding: 5,
  // Unspecified sides are 0
  padding: {
    top: 5,
    left: 20,
  },
});
```

### elementContext

```ts
type ElementContext = 'reference' | 'floating';
```

By default, the floating element is the one being checked for
overflow.

But you can also change the context to `'reference'{:js}` to
instead check its overflow relative to its clipping boundary.

```js
await detectOverflow(state, {
  elementContext: 'reference', // 'floating' by default
});
```

### altBoundary

This is a boolean value which determines whether to check the
alternate `elementContext{:.objectKey}`'s boundary.

For instance, if the `elementContext{:.objectKey}` is
`'floating'{:js}`, and you enable this option, then the boundary
in which overflow is checked for is the `'reference'{:js}`'s
boundary. This only applies if you are using the default
`'clippingAncestors'{:js}` string as the `boundary{:.objectKey}`.

```js
await detectOverflow(state, {
  altBoundary: true, // false by default
});
```
