<PageCard>

# autoPlacement

Chooses the placement that has the most space available
automatically.

<MiddlewareContainer>
  <MiddlewareBadge type="Visibility Optimizer" />
</MiddlewareContainer>

<ShowFor packages={['core']}>

```js
import {autoPlacement} from '@floating-ui/core';
```

</ShowFor>

<ShowFor packages={['dom']}>

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

</ShowFor>

<ShowFor packages={['react']}>

```js
import {autoPlacement} from '@floating-ui/react';
```

</ShowFor>

<ShowFor packages={['react-dom']}>

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

</ShowFor>

<ShowFor packages={['vue']}>

```js
import {autoPlacement} from '@floating-ui/vue';
```

</ShowFor>

<ShowFor packages={['react-native']}>

```js
import {autoPlacement} from '@floating-ui/react-native';
```

</ShowFor>

This is useful when you don't know which placement will be best
for the floating element, or don't want to have to explicitly
specify it.

</PageCard>

<div className="flex flex-col gap-4">
  <Chrome
    label="Scroll the container"
    center
    scrollable="y"
    className="h-96"
  >
    <Floating
      middleware={[
        {
          name: 'autoPlacement',
          options: {
            allowedPlacements: ['top', 'bottom'],
            rootBoundary: 'document',
          },
        },
      ]}
    >
      <div className="grid h-8 w-8 place-items-center border-2 border-dashed border-gray-1000" />
    </Floating>
  </Chrome>
</div>

## Usage

<ShowFor packages={['core', 'dom']}>

```js
computePosition(referenceEl, floatingEl, {
  middleware: [autoPlacement()],
});
```

</ShowFor>

<ShowFor packages={['react', 'react-dom', 'react-native']}>

```js
useFloating({
  middleware: [autoPlacement()],
});
```

</ShowFor>

<ShowFor packages={['vue']}>

```js
useFloating(reference, floating, {
  middleware: [autoPlacement()],
});
```

</ShowFor>

<Notice type="warning" title="Note">
  This is an alternative to `flip(){:js}`, so only one of either can be used.
  See [how they differ here](/docs/autoPlacement#conflict-with-flip).
</Notice>

## Options

These are the options you can pass to `autoPlacement(){:js}`.

```ts
interface AutoPlacementOptions extends DetectOverflowOptions {
  crossAxis?: boolean;
  alignment?: Alignment | null;
  autoAlignment?: boolean;
  allowedPlacements?: Array<Placement>;
}
```

### `crossAxis{:.key}`

default: `false{:js}`

Determines whether a "most space" strategy is also used for the
cross axis (which runs along the alignment of the floating
element). May be desirable when the `allowedPlacements{:.key}`
are all on the same axis.

```js
autoPlacement({
  crossAxis: true,
});
```

### `alignment{:.key}`

default: `undefined{:js}`

Without options, `autoPlacement(){:js}` will choose any of the
`Side{:.class}` placements which fit best, i.e. `'top'{:js}`,
`'right'{:js}`, `'bottom'{:js}`, or `'left'{:js}`.

By specifying an alignment, it will choose those aligned
placements.

```js
autoPlacement({
  // top-start, right-start, bottom-start, left-start
  alignment: 'start',
});
```

### `autoAlignment{:.key}`

default: `true{:js}`

When `alignment{:.key}` is specified, this describes whether to
automatically choose placements with the opposite alignment if
they fit better.

```js
autoPlacement({
  alignment: 'start',
  // Won't also choose 'end' alignments if those fit better
  autoAlignment: false,
});
```

### `allowedPlacements{:.key}`

default: computed subset of `allPlacements{:.const}`

Describes the placements which are allowed to be chosen.

```js
autoPlacement({
  // 'right' and 'left' won't be chosen
  allowedPlacements: ['top', 'bottom'],
});
```

```js
autoPlacement({
  // Only choose these placements
  allowedPlacements: ['top-start', 'bottom-end'],
});
```

### ...detectOverflowOptions

All of [`detectOverflow`](/docs/detectOverflow#options)'s options
can be passed. For instance:

```js
autoPlacement({
  padding: 5, // 0 by default
});
```

### Deriving options from state

You can derive the options from the
[middleware lifecycle state](/docs/middleware#middlewarestate):

```js
autoPlacement((state) => ({
  padding: state.rects.reference.width,
}));
```

## Final placement

The placement returned is always the final one.

<ShowFor packages={['core', 'dom']}>

```js
computePosition(referenceEl, floatingEl, {
  middleware: [autoPlacement()],
}).then(({placement}) => {
  console.log(placement); // any side
});
```

</ShowFor>

<ShowFor packages={['react', 'react-dom', 'react-native']}>

```js
// placement can be any side
const {placement} = useFloating({
  middleware: [autoPlacement()],
});
```

</ShowFor>

<ShowFor packages={['vue']}>

```js
// placement can be any side
const {placement} = useFloating(reference, floating, {
  middleware: [autoPlacement()],
});
```

</ShowFor>

## Conflict with `flip(){:js}`

`flip(){:js}` and `autoPlacement(){:js}` cannot be used together
inside the same middleware array; make sure you choose only one
of them to use.

The reason is they both try to perform work on the placement but
with opposing strategies. Therefore, they will continually try to
change the result or work of the other one, leading to a reset
loop.

- `flip(){:js}` uses a fallback "no space" strategy. Ensures the
  preferred placement is kept unless there is no space left.
- `autoPlacement(){:js}` uses a primary "most space" strategy.
  Always chooses the placement with the most space available.
