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

# autoUpdate

The floating element can detach from its reference element after
the initial positioning, as `computePosition(){:js}` is discrete
and runs only once.

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

To ensure the floating element remains anchored to its reference
element, such as when scrolling and resizing the screen, its
position needs to be continually updated when necessary.

To solve this, `autoUpdate(){:js}` adds listeners that will
automatically call an update function which invokes
`computePosition(){:js}` when necessary. Updates typically take
only ~1ms.

Only call this function when the floating element is open on the
screen.

```js /position/
import {computePosition, autoUpdate} from '@floating-ui/dom';

// This function will get called repeatedly.
function updatePosition() {
  computePosition(referenceEl, floatingEl).then(({x, y}) => {
    // ...
  });
}

const cleanup = autoUpdate(
  referenceEl,
  floatingEl,
  updatePosition
);
```

It returns a cleanup function that should be invoked when the
floating element is removed from the screen.

```js
// Later, when the element is removed from the screen
cleanup();
```

<Notice title="Browser support">
Requires a `ResizeObserver{:.class}` by default, which is supported widely by
all modern browsers. However, depending on your browser  support requirements, you may 
need to provide a polyfill for this. You can find the support table on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#browser_compatibility).
</Notice>

## Options

These are the options you can pass as a fourth argument to
`autoUpdate(){:js}`.

```js
interface Options {
  ancestorScroll?: boolean;
  ancestorResize?: boolean;
  elementResize?: boolean;
  layoutShift?: boolean;
  animationFrame?: boolean;
}
```

### ancestorScroll

default: `true{:js}`

Whether to update the position when an overflow ancestor is
scrolled.

```js
const cleanup = autoUpdate(referenceEl, floatingEl, update, {
  ancestorScroll: false,
});
```

### ancestorResize

default: `true{:js}`

Whether to update the position when an overflow ancestor is
resized. This uses the `resize{:.string}` event.

```js
const cleanup = autoUpdate(referenceEl, floatingEl, update, {
  ancestorResize: false,
});
```

### elementResize

default: `true{:js}`

Whether to update the position when either the reference or
floating elements resized. This uses a `ResizeObserver{:.class}`.

To support old browsers, polyfill the constructor, or disable
this option and update manually when the elements resize.

```js
const cleanup = autoUpdate(referenceEl, floatingEl, update, {
  elementResize: false,
});
```

<Notice type="note" title="Testing environments">
JSDOM does not support `ResizeObserver{:.class}`. A polyfill or check like the 
following will work:

<br />

```js
autoUpdate(referenceEl, floatingEl, update, {
  elementResize: typeof ResizeObserver === 'function',
});
```

</Notice>

### layoutShift

default: `true{:js}`

Whether to update the position of the floating element if the
reference element moved on the screen as the result of layout
shift.

```js
const cleanup = autoUpdate(referenceEl, floatingEl, update, {
  layoutShift: false,
});
```

### animationFrame

default: `false{:js}`

Whether to update the position of the floating element on every
animation frame if required. While optimized for performance, it
should be used sparingly in the following cases:

- The reference element is animating on the screen with
  `transform`s.
- Ensure a nested floating element is anchored when it's outside
  of ancestor floating elements' scrolling contexts.

```js
const cleanup = autoUpdate(referenceEl, floatingEl, update, {
  animationFrame: true,
});
```
