> For the complete documentation index, see [llms.txt](https://analog.groupthought.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://analog.groupthought.com/reference/alpine/float.md).

# x-float

The directive and magic for floating one element next to another with Floating UI: placement, collision handling, sizing, and update strategies.

The directive and magic for floating one element next to another with [Floating UI](https://floating-ui.com/): placement, collision handling, sizing, and update strategies.

| Directive / magic                                    | What it does                                                                                                                                                                                                |
| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `x-float="reference"`                                | Floats the element next to the reference element. A falsey expression disables floating                                                                                                                     |
| `x-float="{ … }"`                                    | Options object instead of a bare reference (see Options)                                                                                                                                                    |
| `.top` / `.bottom-start` / `.left-end` / …           | Preferred placement, any Floating UI placement string. With no placement modifier, auto placement picks the side with the most space                                                                        |
| `.offset` / `.offset.10px`                           | Distance from the reference (bare `.offset` is 20px)                                                                                                                                                        |
| `.flip`                                              | Flips to the opposite side when out of space. Throws when combined with `.auto`                                                                                                                             |
| `.auto` / `.auto-x` / `.auto-y`                      | Picks the side with the most space: any side, left/right only, or top/bottom only                                                                                                                           |
| `.shift` / `.shift-cross` / `.shift-both`            | Slides along the reference to stay in view: main axis, cross axis, or both                                                                                                                                  |
| `.cover`                                             | Positions over the reference instead of beside it                                                                                                                                                           |
| `.fit-x` / `.fit-y`                                  | Caps `max-width` / `max-height` to the available space                                                                                                                                                      |
| `.match`                                             | Matches the reference's width (its height for left/right placements)                                                                                                                                        |
| `.pad` / `.pad.10px`                                 | Boundary padding used by `flip`, `shift`, and `fit` (bare `.pad` is 5px)                                                                                                                                    |
| `.update`                                            | Repositions on scroll and resize                                                                                                                                                                            |
| `.absolute` / `.transform` / `.transform3d` / `.css` | Positioning strategy. Default is `fixed` `left`/`top`; the transform strategies translate instead; `css` writes custom properties and leaves applying them to your stylesheet                               |
| `x-float:arrow`                                      | The arrow element: pinned to the edge facing the reference, rotated to point at it                                                                                                                          |
| `$float`                                             | `referenceEl` (get/set), `isPositioned`, `placement`, `side`, `alignment`, `matchSizeEnabled` (get/set), `updatePosition()`, `enableAutoUpdate()`, `disableAutoUpdate()`, `reset()`, `middleware` (get/set) |

This is the positioning layer under the overlay plugins: the modifiers you pass on [x-popup:popup](/reference/alpine/popup.md), [x-popover:panel](/reference/alpine/popover.md), [x-menu:popup](/reference/alpine/menu.md), and [x-select:panel](/reference/alpine/select.md) are these modifiers, forwarded. A falsey expression disables floating and resets the position. Gate the expression on visibility so the plugin only measures visible panels.

## Examples

### A basic float

Use `x-float` with the reference element as the expression, gated on visibility:

```html
<div x-data="{ open: false }">
  <button x-ref="reference" @click="open = !open">Toggle</button>
  <div x-show="open" x-float="open && $refs.reference">
    I'm floating!
  </div>
</div>
```

While the expression is falsey, the plugin doesn't calculate a position and `$float.isPositioned` stays false. Use it to hide the element until positioning finishes.

### Choosing a side

Use a placement modifier with `.offset` to say where the element should sit:

```html
<div x-show="open" x-float.bottom-end.offset.10px="open && $refs.reference">…</div>
```

Any Floating UI placement works: a side (`top`, `right`, `bottom`, `left`), optionally with an alignment (`-start`, `-end`). Leave the placement off and the plugin picks the side with the most space.

### Staying in view

Use `.flip`, `.shift`, and `.fit-y` together so the element lands somewhere visible, with `.pad` for the distance from the boundary:

```html
<div x-float.bottom.offset.5px.flip.shift.fit-y.pad.10px="…">…</div>
```

`flip` swaps to the opposite side when the preferred one is full, `shift` slides the element along the reference, and `fit-y` caps its height to what fits. This is the combination the `custom-select` snippet builds for its panel; `core-popover` uses `flip.shift.update.pad.5px` for tooltips that follow scrolling.

### Matching the reference's size

Use `.match` to give the element the reference's width:

```html
<div x-float.bottom-start.match="…">…</div>
```

Dropdown panels use this to line up with their button. It is part of the default modifier string on `x-select:panel`. On a left or right placement, `.match` matches the height instead.

### Reading the resolved placement

Use `$float.placement`, `$float.side`, and `$float.alignment` to style the element by where it actually landed:

```html
<div
  x-float.bottom.flip="…"
  x-effect="if ($float.side != null) $el.dataset.side = $float.side"
  class="data-[side=bottom]:origin-top data-[side=top]:origin-bottom"
>
  …
</div>
```

With `flip` or `auto`, the requested side and the landed side can differ. The `custom-select` popup copies all three onto `data-` attributes so its open animation scales from the correct edge.

### The css strategy

Use the `css` modifier when your stylesheet should decide whether the position applies:

```html
<div
  x-float.css.bottom-end.update="window.headerCartButton"
  :class="{ 'md:!start-[--float-x]': $float.isPositioned }"
>
  …
</div>
```

Instead of writing inline styles, `css` sets `--float-x` and `--float-y` on the element (`fit` and `match` write `--float-max-width`, `--float-max-height`, `--float-width`, `--float-height`). The add-to-cart notification floats itself under the header cart button on desktop this way, while mobile ignores the variables and keeps its own layout.

### Options from state

Pass an options object with getters for reactive values instead of a bare reference:

```html
<div
  x-float.bottom.flip="{
    referenceEl: $refs.dot,
    get rootBoundary() { return $refs.hotspotsContainerEl }
  }"
>
  …
</div>
```

The hotspot tooltips pass their image container as `rootBoundary`, so `flip` and `shift` react to the edges of the image rather than the viewport. The expression is reactive: when a getter's state changes, the float updates.

## Options

| Option          | What it does                                                                                                          |
| --------------- | --------------------------------------------------------------------------------------------------------------------- |
| `referenceEl`   | The reference element (instead of a bare element expression)                                                          |
| `strategy`      | `'fixed'`, `'absolute'`, `'transform'`, `'transform3d'`, or `'css'`                                                   |
| `offset`        | Distance from the reference, in pixels                                                                                |
| `padding`       | Boundary padding for `flip`, `shift`, and `fit`                                                                       |
| `flip`          | Same as `.flip`                                                                                                       |
| `shift`         | `true`, `'cross'`, or `'both'`                                                                                        |
| `cover`         | Same as `.cover`                                                                                                      |
| `autoPlacement` | `true`, `'x'`, or `'y'`                                                                                               |
| `fitX` / `fitY` | Same as `.fit-x` / `.fit-y`                                                                                           |
| `matchSize`     | Same as `.match`                                                                                                      |
| `autoUpdate`    | Same as `.update`                                                                                                     |
| `initialUpdate` | Set `false` to skip positioning until told (the overlay plugins do this and call `$float.enableAutoUpdate()` on open) |
| `rootBoundary`  | The Floating UI boundary that `flip`, `shift`, and `fit` respect (default `'viewport'`)                               |

`$float.middleware` accepts an array of custom [Floating UI middleware](https://floating-ui.com/docs/middleware), which run after `offset` and before everything else. Most sections use [x-popup](/reference/alpine/popup.md) or one of its child plugins instead. They set the reference, open state, and auto-update.
