Skip to content

Floating Position

hookpositioningfloatingpopovertooltip

Position floating content relative to a trigger element. Handles collision detection, auto-flipping to opposite sides, and viewport boundary shifting.

tsx
const triggerRef = useRef<HTMLButtonElement>(null);const { position, contentRef } = useFloatingPosition({  triggerRef,  open,  side: "bottom",  align: "center",});

Installation

$pnpm exec dgadd add ui/floating-position
[Installs to]src/hooks/use-floating-position.ts[Item]ui/floating-position

dgadd is not public on npm yet. Until the first release, pack @diffgazer/add from the repository and install that tarball into this app, which is what puts dgadd on pnpm exec.

UI components require Tailwind CSS v4. Local copy mode imports src/styles/styles.css; package mode uses @diffgazer/ui CSS once packages are available.

Parameters

NameTypeDefaultDescription
triggerRefrequiredRefObject<HTMLElement | null>Ref to the trigger element that the floating content is positioned relative to.
openrequiredbooleanWhether the floating content is open. Position is computed when true, reset to null when false.
side"top" | "bottom" | "left" | "right""top"Preferred side for positioning. Auto-flips if there isn't enough space.
align"start" | "center" | "end""center"Alignment along the cross axis.
sideOffsetnumber6Distance in pixels between the trigger and floating content along the side axis.
alignOffsetnumber0Offset in pixels along the alignment axis.
collisionPaddingnumber8Minimum distance in pixels from viewport edges when avoiding collisions.
avoidCollisionsbooleantrueWhether to automatically flip sides and shift position to stay within viewport.

Returns

UseFloatingPositionReturnObject containing computed position and a ref for the floating content element.
NameTypeDefaultDescription
positionrequiredFloatingPosition | nullComputed position with x, y coordinates and resolved side/align. Null when closed.
contentRefrequiredRefCallback<HTMLDivElement>Callback ref to attach to the floating content element. Attaching, replacing, or removing the node restarts measurement and observer subscriptions.

Examples

Basic Positioning

Preview

Notes

Collision Detection

When content would overflow the viewport, the hook tries the opposite side first, then cross-axis sides, and finally shifts the position to stay within bounds.

Layout Effect

Uses useLayoutEffect to compute position synchronously before paint, preventing visual flicker.

Late Attachment

The content callback ref participates in the positioning lifecycle, so content mounted after the overlay opens is measured immediately and receives resize and scroll subscriptions.

Used By

Built into PopoverContent for automatic positioning of popovers and tooltips.

Source

Highlighted source loads after this disclosure opens. Browse the source repository.