React-optimized positioning middleware for controlling floating element behavior. Each middleware function wraps the core @floating-ui/dom functionality with React dependency tracking for optimal performance, preventing unnecessary recalculations when dependencies haven't changed.
type Derivable<T> = T | ((state: MiddlewareState) => T);
interface MiddlewareState {
x: number;
y: number;
initialPlacement: Placement;
placement: Placement;
strategy: Strategy;
middlewareData: MiddlewareData;
rects: ElementRects;
elements: Elements;
}Translates the floating element along specified axes to create space between reference and floating elements.
/**
* Modifies the placement by translating the floating element along the specified axes
* @param options - Offset configuration or number (shorthand for mainAxis, can be derivable/function)
* @param deps - React dependency list for optimization
* @returns Middleware function
*/
function offset(
options?: OffsetOptions | number | Derivable<OffsetOptions>,
deps?: React.DependencyList
): Middleware;
interface OffsetOptions {
mainAxis?: number;
crossAxis?: number;
alignmentAxis?: number | null;
}Usage Examples:
import { useFloating, offset } from '@floating-ui/react-dom';
// Simple offset
const { refs, floatingStyles } = useFloating({
middleware: [offset(10)] // 10px offset along main axis
});
// Complex offset
const { refs, floatingStyles } = useFloating({
middleware: [
offset({
mainAxis: 10, // Distance along placement axis
crossAxis: 5, // Distance perpendicular to placement
alignmentAxis: 0 // Distance along alignment axis
})
]
});
// Dynamic offset with dependencies
const [distance, setDistance] = useState(10);
const { refs, floatingStyles } = useFloating({
middleware: [offset(distance, [distance])]
});Keeps the floating element in view by shifting it when it would overflow the clipping boundary.
/**
* Optimizes visibility by shifting the floating element to stay in view
* @param options - Shift configuration options (can be derivable/function)
* @param deps - React dependency list for optimization
* @returns Middleware function
*/
function shift(
options?: ShiftOptions | Derivable<ShiftOptions>,
deps?: React.DependencyList
): Middleware;
interface ShiftOptions {
mainAxis?: boolean;
crossAxis?: boolean;
limiter?: {
fn: (state: MiddlewareState) => Coords;
options?: any;
};
boundary?: Boundary;
rootBoundary?: RootBoundary;
elementContext?: ElementContext;
altBoundary?: boolean;
padding?: Padding;
}
type Boundary = 'clippingAncestors' | Element | Array<Element> | Rect;
type RootBoundary = 'viewport' | 'document' | Rect;
type ElementContext = 'reference' | 'floating';
type Padding = number | Partial<SideObject>;Usage Examples:
import { useFloating, shift, limitShift } from '@floating-ui/react-dom';
// Basic shift
const { refs, floatingStyles } = useFloating({
middleware: [shift()]
});
// Shift with padding
const { refs, floatingStyles } = useFloating({
middleware: [
shift({
padding: 8 // 8px padding from viewport edges
})
]
});
// Shift with limiter
const { refs, floatingStyles } = useFloating({
middleware: [
shift({
limiter: limitShift({
offset: 25 // Stop shifting after 25px
})
})
]
});
// Cross-axis shifting
const { refs, floatingStyles } = useFloating({
middleware: [
shift({
crossAxis: true, // Allow shifting perpendicular to placement
boundary: document.querySelector('#container')
})
]
});Changes the placement of the floating element to keep it in view when the preferred placement would cause overflow.
/**
* Optimizes visibility by flipping placement to avoid overflow
* @param options - Flip configuration options (can be derivable/function)
* @param deps - React dependency list for optimization
* @returns Middleware function
*/
function flip(
options?: FlipOptions | Derivable<FlipOptions>,
deps?: React.DependencyList
): Middleware;
interface FlipOptions {
mainAxis?: boolean;
crossAxis?: boolean;
fallbackPlacements?: Array<Placement>;
fallbackStrategy?: 'bestFit' | 'initialPlacement';
fallbackAxisSideDirection?: 'none' | 'start' | 'end';
flipAlignment?: boolean;
boundary?: Boundary;
rootBoundary?: RootBoundary;
elementContext?: ElementContext;
altBoundary?: boolean;
padding?: Padding;
}Usage Examples:
import { useFloating, flip } from '@floating-ui/react-dom';
// Basic flip
const { refs, floatingStyles } = useFloating({
placement: 'top',
middleware: [flip()] // Will flip to bottom if top overflows
});
// Custom fallback placements
const { refs, floatingStyles } = useFloating({
placement: 'top',
middleware: [
flip({
fallbackPlacements: ['top-start', 'top-end', 'bottom', 'right']
})
]
});
// Flip with boundary
const { refs, floatingStyles } = useFloating({
middleware: [
flip({
boundary: document.querySelector('#scroll-container'),
padding: 8
})
]
});Positions an arrow element to point from the floating element to the reference element.
/**
* Positions an arrow element centered to the reference element
* @param options - Arrow configuration with element ref or DOM element (can be derivable/function)
* @param deps - React dependency list for optimization
* @returns Middleware function
*/
function arrow(
options: ArrowOptions | Derivable<ArrowOptions>,
deps?: React.DependencyList
): Middleware;
interface ArrowOptions {
element: React.MutableRefObject<Element | null> | Element | null;
padding?: Padding;
}Usage Examples:
import React, { useRef } from 'react';
import { useFloating, arrow, offset } from '@floating-ui/react-dom';
function TooltipWithArrow() {
const arrowRef = useRef<HTMLDivElement>(null);
const { refs, floatingStyles, middlewareData } = useFloating({
placement: 'top',
middleware: [
offset(8),
arrow({ element: arrowRef, padding: 4 })
]
});
const arrowX = middlewareData.arrow?.x;
const arrowY = middlewareData.arrow?.y;
return (
<>
<button ref={refs.setReference}>Reference</button>
<div ref={refs.setFloating} style={floatingStyles}>
Tooltip content
<div
ref={arrowRef}
style={{
position: 'absolute',
left: arrowX != null ? `${arrowX}px` : '',
top: arrowY != null ? `${arrowY}px` : '',
width: '8px',
height: '8px',
backgroundColor: 'inherit',
transform: 'rotate(45deg)'
}}
/>
</div>
</>
);
}Provides data to change the size of the floating element, such as preventing overflow or matching reference width.
/**
* Provides data to change floating element size based on available space
* @param options - Size configuration with apply function (can be derivable/function)
* @param deps - React dependency list for optimization
* @returns Middleware function
*/
function size(
options?: SizeOptions | Derivable<SizeOptions>,
deps?: React.DependencyList
): Middleware;
interface SizeOptions {
apply?: (args: {
availableWidth: number;
availableHeight: number;
elements: Elements;
rects: ElementRects;
}) => void | Promise<void>;
boundary?: Boundary;
rootBoundary?: RootBoundary;
elementContext?: ElementContext;
altBoundary?: boolean;
padding?: Padding;
}
interface Elements {
reference: Element;
floating: HTMLElement;
}
interface ElementRects {
reference: Rect;
floating: Rect;
}
interface Rect {
x: number;
y: number;
width: number;
height: number;
}Usage Examples:
import { useFloating, size } from '@floating-ui/react-dom';
// Constrain height to available space
const { refs, floatingStyles } = useFloating({
middleware: [
size({
apply({ availableHeight, elements }) {
Object.assign(elements.floating.style, {
maxHeight: `${availableHeight}px`,
overflow: 'auto'
});
}
})
]
});
// Match reference element width
const { refs, floatingStyles } = useFloating({
middleware: [
size({
apply({ rects, elements }) {
Object.assign(elements.floating.style, {
width: `${rects.reference.width}px`
});
}
})
]
});Provides data to hide the floating element when it's not in the same clipping context as the reference element.
/**
* Provides data to hide floating element in applicable situations
* @param options - Hide configuration options (can be derivable/function)
* @param deps - React dependency list for optimization
* @returns Middleware function
*/
function hide(
options?: HideOptions | Derivable<HideOptions>,
deps?: React.DependencyList
): Middleware;
interface HideOptions {
strategy?: 'referenceHidden' | 'escaped';
boundary?: Boundary;
rootBoundary?: RootBoundary;
elementContext?: ElementContext;
altBoundary?: boolean;
padding?: Padding;
}Automatically chooses the placement with the most available space, alternative to flip middleware.
/**
* Optimizes visibility by choosing placement with most available space
* @param options - Auto placement configuration (can be derivable/function)
* @param deps - React dependency list for optimization
* @returns Middleware function
*/
function autoPlacement(
options?: AutoPlacementOptions | Derivable<AutoPlacementOptions>,
deps?: React.DependencyList
): Middleware;
interface AutoPlacementOptions {
crossAxis?: boolean;
alignment?: Alignment | null;
allowedPlacements?: Array<Placement>;
autoAlignment?: boolean;
boundary?: Boundary;
rootBoundary?: RootBoundary;
elementContext?: ElementContext;
altBoundary?: boolean;
padding?: Padding;
}
type Alignment = 'start' | 'end';Provides improved positioning for inline reference elements that span multiple lines.
/**
* Improves positioning for inline reference elements spanning multiple lines
* @param options - Inline configuration options (can be derivable/function)
* @param deps - React dependency list for optimization
* @returns Middleware function
*/
function inline(
options?: InlineOptions | Derivable<InlineOptions>,
deps?: React.DependencyList
): Middleware;
interface InlineOptions {
x?: number;
y?: number;
padding?: Padding;
}Built-in limiter function that stops shift middleware at a certain point. Returns a limiter object designed to be used with the shift middleware's limiter option.
/**
* Built-in limiter that stops shift() at a certain point
* @param options - Limit shift configuration (can be derivable/function)
* @param deps - React dependency list for optimization
* @returns Limiter object with fn and options properties for use with shift middleware
*/
function limitShift(
options?: LimitShiftOptions | Derivable<LimitShiftOptions>,
deps?: React.DependencyList
): {
fn: (state: MiddlewareState) => Coords;
options: any;
};
interface LimitShiftOptions {
offset?: number | ((args: { placement: Placement; rects: ElementRects }) => number) | {
mainAxis?: number;
crossAxis?: number;
};
mainAxis?: boolean;
crossAxis?: boolean;
}