Skip to content

useFloating

The core composable for positioning floating elements relative to anchor elements.

Signature

ts
function useFloating(
  anchorEl: Ref<AnchorElement>,
  floatingEl: Ref<FloatingElement>,
  options?: UseFloatingOptions
): FloatingContext

Parameters

ParameterTypeRequiredDescription
anchorElRef<AnchorElement>YesReference to the anchor element
floatingElRef<FloatingElement>YesReference to the floating element
optionsUseFloatingOptionsNoConfiguration options

Options

ts
interface UseFloatingOptions {
  id?: string
  placement?: MaybeRefOrGetter<Placement>
  strategy?: MaybeRefOrGetter<Strategy>
  transform?: MaybeRefOrGetter<boolean>
  middlewares?: MaybeRefOrGetter<Middleware[]>
  autoUpdate?: boolean | AutoUpdateOptions
  open?: Ref<boolean>
  onOpenChange?: (open: boolean, reason: OpenChangeReason, event?: Event) => void
}
OptionTypeDefaultDescription
idstringundefinedOptional stable identifier (used by useFloatingTree)
placementMaybeRefOrGetter<Placement>'bottom'Desired placement of the floating element
strategyMaybeRefOrGetter<Strategy>'absolute'Positioning strategy ('absolute' or 'fixed')
transformMaybeRefOrGetter<boolean>trueUse CSS transform for positioning
middlewaresMaybeRefOrGetter<Middleware[]>[]Array of middleware functions
autoUpdateboolean | AutoUpdateOptionstrueAuto-update position on scroll/resize
openRef<boolean>ref(false)Control open/closed state
onOpenChange(open, reason, event?) => voidundefinedCallback when open state changes

Return Value

ts
interface FloatingContext {
  id?: string
  x: Readonly<Ref<number>>
  y: Readonly<Ref<number>>
  strategy: Readonly<Ref<Strategy>>
  placement: Readonly<Ref<Placement>>
  middlewareData: Readonly<Ref<MiddlewareData>>
  isPositioned: Readonly<Ref<boolean>>
  floatingStyles: Readonly<Ref<FloatingStyles>>
  update: () => void
  refs: {
    anchorEl: Ref<AnchorElement>
    floatingEl: Ref<FloatingElement>
    arrowEl: Ref<HTMLElement | null>
  }
  open: Readonly<Ref<boolean>>
  setOpen: (open: boolean, reason?: OpenChangeReason, event?: Event) => void
}
PropertyTypeDescription
idstring | undefinedStable identifier for tree-aware interactions
xReadonly<Ref<number>>X-coordinate of the floating element
yReadonly<Ref<number>>Y-coordinate of the floating element
strategyReadonly<Ref<Strategy>>Positioning strategy
placementReadonly<Ref<Placement>>Final computed placement
middlewareDataReadonly<Ref<MiddlewareData>>Data from middleware
isPositionedReadonly<Ref<boolean>>Whether element has been positioned
floatingStylesReadonly<Ref<FloatingStyles>>CSS styles to apply
update() => voidManually update position
refsobjectReferences to anchor, floating, and arrow elements
openReadonly<Ref<boolean>>Open/closed state
setOpen(open, reason?, event?) => voidExplicitly set open state with optional reason

Types

AnchorElement

ts
type AnchorElement = HTMLElement | VirtualElement | null

FloatingElement

ts
type FloatingElement = HTMLElement | null

FloatingStyles

ts
interface FloatingStyles {
  position: Strategy
  top: string
  left: string
  transform?: string
  'will-change'?: string
  [key: `--${string}`]: any  // CSS custom properties
}

OpenChangeReason

ts
type OpenChangeReason =
  | 'programmatic'
  | 'anchor-click'
  | 'hover'
  | 'focus'
  | 'blur'
  | 'escape-key'
  | 'tree-ancestor-close'

Describes the reason why the open state changed:

  • 'programmatic' - Changed via setOpen() or open.value = ...
  • 'anchor-click' - Triggered by clicking the anchor element
  • 'hover' - Triggered by hovering over the anchor
  • 'focus' - Triggered by focusing the anchor
  • 'blur' - Triggered by blurring the anchor
  • 'escape-key' - Triggered by pressing the Escape key
  • 'tree-ancestor-close' - Triggered by a parent node closing in a tree hierarchy

Examples

Basic Usage

vue
<script setup>
import { ref } from 'vue'
import { useFloating } from 'v-float'

const anchorEl = ref(null)
const floatingEl = ref(null)

const { floatingStyles } = useFloating(anchorEl, floatingEl)
</script>

<template>
  <button ref="anchorEl">Anchor</button>
  <div ref="floatingEl" :style="floatingStyles">
    Floating content
  </div>
</template>

With Placement

vue
<script setup>
import { useFloating } from 'v-float'

const { floatingStyles } = useFloating(anchorEl, floatingEl, {
  placement: 'top-start'
})
</script>

With Middleware

vue
<script setup>
import { useFloating, offset, flip, shift } from 'v-float'

const { floatingStyles } = useFloating(anchorEl, floatingEl, {
  placement: 'top',
  middlewares: [
    offset(8),
    flip(),
    shift({ padding: 5 })
  ]
})
</script>

Reactive Placement

vue
<script setup>
import { ref } from 'vue'
import { useFloating } from 'v-float'

const placement = ref('top')

const { floatingStyles } = useFloating(anchorEl, floatingEl, {
  placement
})

// Change placement dynamically
placement.value = 'bottom'
</script>

With Open State and Callback

vue
<script setup>
import { ref } from 'vue'
import { useFloating } from 'v-float'

const isOpen = ref(false)

const { floatingStyles, setOpen } = useFloating(anchorEl, floatingEl, {
  open: isOpen,
  onOpenChange: (open, reason, event) => {
    console.log(`Floating element ${open ? 'opened' : 'closed'} via ${reason}`)
  }
})

// Programmatically control open state
const toggleOpen = () => {
  setOpen(!isOpen.value, 'programmatic')
}
</script>

See Also

  • offset - Offset the floating element
  • flip - Flip to alternative placement
  • shift - Shift to keep in view
  • arrow - Position an arrow element

Released under the MIT License.