Core positioning functionality providing the main computePosition function for calculating optimal floating element coordinates.
Main function that computes x and y coordinates for positioning floating elements relative to reference elements.
/**
* Computes the x and y coordinates that will place the floating element
* next to a given reference element.
* This export does not have any platform interface logic. You will need to
* write one for the platform you are using Floating UI with.
*
* @param reference - The reference element
* @param floating - The floating element
* @param config - Configuration object
* @returns Promise resolving to positioning result
*/
function computePosition(
reference: unknown,
floating: unknown,
config: ComputePositionConfig
): Promise<ComputePositionReturn>;
interface ComputePositionConfig {
/** Object to interface with the current platform (required) */
platform: Platform;
/** Where to place the floating element relative to the reference element */
placement?: Placement;
/** The strategy to use when positioning the floating element */
strategy?: Strategy;
/** Array of middleware objects to modify positioning or provide data */
middleware?: Array<Middleware | null | undefined | false>;
}
interface ComputePositionReturn {
/** Final x coordinate for the floating element */
x: number;
/** Final y coordinate for the floating element */
y: number;
/** The final chosen placement of the floating element */
placement: Placement;
/** The strategy used to position the floating element */
strategy: Strategy;
/** Object containing data returned from all middleware, keyed by their name */
middlewareData: MiddlewareData;
}Usage Examples:
import { computePosition, offset, flip } from "@floating-ui/core";
// Basic positioning
const result = await computePosition(button, tooltip, {
placement: "top",
platform: domPlatform
});
// With middleware
const result = await computePosition(button, dropdown, {
placement: "bottom-start",
strategy: "absolute",
middleware: [
offset(10),
flip(),
shift({ padding: 8 })
],
platform: domPlatform
});
// Access computed values
console.log(`Position: ${result.x}, ${result.y}`);
console.log(`Final placement: ${result.placement}`);
console.log(`Middleware data:`, result.middlewareData);Required platform interface for DOM operations. Must be implemented for each platform (DOM, React Native, etc.). The first three methods are required; all others are optional but may be needed for advanced features.
interface Platform {
/** Get element rectangles (required) */
getElementRects(args: {
reference: ReferenceElement;
floating: FloatingElement;
strategy: Strategy;
}): Promise<ElementRects> | ElementRects;
/** Get clipping rectangle (required) */
getClippingRect(args: {
element: any;
boundary: Boundary;
rootBoundary: RootBoundary;
strategy: Strategy;
}): Promise<Rect> | Rect;
/** Get element dimensions (required) */
getDimensions(element: any): Promise<Dimensions> | Dimensions;
/** Convert offset parent relative rect to viewport relative (optional) */
convertOffsetParentRelativeRectToViewportRelativeRect?(args: {
elements?: Elements;
rect: Rect;
offsetParent: any;
strategy: Strategy;
}): Promise<Rect> | Rect;
/** Get offset parent element (optional) */
getOffsetParent?(element: any): Promise<any> | any;
/** Check if value is an element (optional) */
isElement?(value: any): Promise<boolean> | boolean;
/** Get document element (optional) */
getDocumentElement?(element: any): Promise<any> | any;
/** Get client rectangles for inline elements (optional) */
getClientRects?(element: any): Promise<Array<ClientRectObject>> | Array<ClientRectObject>;
/** Check if element uses RTL direction (optional) */
isRTL?(element: any): Promise<boolean> | boolean;
/** Get element scale factors (optional) */
getScale?(element: any): Promise<{x: number; y: number}> | {x: number; y: number};
}Interface for creating custom middleware that can modify positioning behavior.
interface Middleware {
/** Unique name for the middleware */
name: string;
/** Options passed to the middleware */
options?: any;
/** Function that performs the middleware logic */
fn: (state: MiddlewareState) => Promise<MiddlewareReturn> | MiddlewareReturn;
}
interface MiddlewareState {
/** Current x coordinate */
x: number;
/** Current y coordinate */
y: number;
/** Initial placement before middleware modifications */
initialPlacement: Placement;
/** Current placement (may be modified by middleware) */
placement: Placement;
/** Positioning strategy */
strategy: Strategy;
/** Data from previously executed middleware */
middlewareData: MiddlewareData;
/** Reference and floating elements */
elements: Elements;
/** Element rectangles */
rects: ElementRects;
/** Platform interface */
platform: Platform;
}
interface MiddlewareReturn {
/** New x coordinate (optional) */
x?: number;
/** New y coordinate (optional) */
y?: number;
/** Data to store in middlewareData (optional) */
data?: { [key: string]: any };
/** Reset positioning with new placement or rects (optional) */
reset?: boolean | {
placement?: Placement;
rects?: boolean | ElementRects;
};
}
interface MiddlewareData {
[key: string]: any;
arrow?: Partial<Coords> & { centerOffset: number; alignmentOffset?: number };
autoPlacement?: { index?: number; overflows: Array<{ placement: Placement; overflows: Array<number> }> };
flip?: { index?: number; overflows: Array<{ placement: Placement; overflows: Array<number> }> };
hide?: { referenceHidden?: boolean; escaped?: boolean; referenceHiddenOffsets?: SideObject; escapedOffsets?: SideObject };
offset?: Coords & { placement: Placement };
shift?: Coords & { enabled: { [key in Axis]: boolean } };
}Custom Middleware Example:
// Custom middleware that adds a random offset
const randomOffset = (): Middleware => ({
name: "randomOffset",
fn({ x, y }) {
return {
x: x + Math.random() * 10 - 5,
y: y + Math.random() * 10 - 5,
data: { randomApplied: true }
};
}
});
// Use in computePosition
const result = await computePosition(reference, floating, {
middleware: [randomOffset()],
platform: domPlatform
});// Element types
type ReferenceElement = any;
type FloatingElement = any;
interface Elements {
reference: ReferenceElement;
floating: FloatingElement;
}
// Boundary types
type Boundary = any;
type RootBoundary = "viewport" | "document" | Rect;
type ElementContext = "reference" | "floating";
// Function option type
type Derivable<T> = (state: MiddlewareState) => T;