Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Shift

Shifts the floating element to keep it in view.

This prevents the floating element from overflowing along its axis of alignment, thereby preserving the side it's placed on.

Type: Visibility Optimizer

Usage

use floating_ui_core::{compute_position, ComputePositionConfig, Shift, ShiftOptions};

compute_position(
    reference_el,
    floating_el,
    ComputePositionConfig::new(platform)
        .middleware(vec![
            Box::new(Shift::new(ShiftOptions::default())),
        ]),
);

Options

These are the options you can pass to Shift.

pub struct ShiftOptions<Element, Window> {
    pub detect_overflow: Option<DetectOverflowOptions<Element>>,
    pub main_axis: Option<bool>,
    pub cross_axis: Option<bool>,
    pub limiter: Option<Box<dyn Limiter<Element, Window>>>,
}

pub trait Limiter<Element, Window>: Clone + PartialEq {
    fn compute(&self, state: MiddlewareState<Element, Window>) -> Coords;
}

main_axis

Default: true

This is the main axis in which shifting is applied.

  • x-axis for Top and Bottom placements
  • y-axis for Left and Right placements
Shift::new(ShiftOptions::default().main_axis(false))

cross_axis

Default: false

This is the cross axis in which shifting is applied, the opposite axis of main_axis.

Enabling this can lead to the floating element overlapping the reference element, which may not be desired and is often replaced by the Flip middleware.

Shift::new(ShiftOptions::default().cross_axis(true))

limiter

Default: no-op

This accepts a struct instance that limits the shifting done, in order to prevent detachment or “overly-eager” behavior. The behavior is to stop shifting once the opposite edges of the elements are aligned.

Shift::new(ShiftOptions::default().limiter(
    Box::new(LimitShift::new(
        LimitShiftOptions::default()
    )),
))

This struct itself takes options.

pub struct LimitShiftOptions<'a, Element, Window> {
    pub offset: Option<Derivable<'a, Element, Window, LimitShiftOffset>>,
    pub main_axis: Option<bool>,
    pub cross_axis: Option<bool>,
}

pub enum LimitShiftOffset {
    Value(f64),
    Values(LimitShiftOffsetValues),
}

pub struct LimitShiftOffsetValues {
    pub main_axis: Option<f64>,
    pub cross_axis: Option<f64>,
}

main_axis

Default: true

Whether to apply limiting on the main axis.

Shift::new(ShiftOptions::default().limiter(
    Box::new(LimitShift::new(
        LimitShiftOptions::default().main_axis(false)
    )),
))

cross_axis

Default: true

Whether to apply limiting on the cross axis.

Shift::new(ShiftOptions::default().limiter(
    Box::new(LimitShift::new(
        LimitShiftOptions::default().cross_axis(false)
    )),
))

offset

Default: 0.0

This will offset when the limiting starts. A positive number will start limiting earlier, while negative later.

Shift::new(ShiftOptions::default().limiter(
    Box::new(LimitShift::new(
        // Start limiting 5px earlier
        LimitShiftOptions::default().offset(LimitShiftOffset::Value(5.0)),
    )),
))

You may also pass a struct instance to configure both axes:

Shift::new(ShiftOptions::default().limiter(
    Box::new(LimitShift::new(
        LimitShiftOptions::default().offset(LimitShiftOffset::Values(
            LimitShitOffsetValues::default()
                .main_axis(10.0)
                .cross_axis(5.0),
        )),
    )),
))

detect_overflow

All of detect_overflow's options can be passed. For instance:

Shift::new(ShiftOptions::default().detect_overflow(
    DetectOvverflowOptions::default().padding(Padding::All(5.0)),
))

Data

The following data is available in middleware_data under the SHIFT_NAME key:

middleware_data.get_as::<ShiftData>(SHIFT_NAME)
pub struct ShiftData {
    pub x: f64,
    pub y: f64,
}

x and y represent how much the floating element has been shifted along that axis. The values are offsets, and therefore can be negative.

See Also