shift
A visibility optimizer that shifts the floating element along the specified axes in order to keep it in view.
This is useful for preventing overflow while maintaining the desired placement as best as possible.
Usage
import {computePosition, shift} from '@floating-ui/dom';
computePosition(referenceEl, floatingEl, {
middleware: [shift()],
});
import {computePosition, shift} from '@floating-ui/dom';
computePosition(referenceEl, floatingEl, {
middleware: [shift()],
});
Options
These are the options you can pass to shift()
shift()
.
interface Options extends DetectOverflowOptions {
mainAxis?: boolean;
crossAxis?: boolean;
limiter?: {
fn: (state: MiddlewareState) => Coords;
options?: any;
};
}
interface Options extends DetectOverflowOptions {
mainAxis?: boolean;
crossAxis?: boolean;
limiter?: {
fn: (state: MiddlewareState) => Coords;
options?: any;
};
}
mainAxis
default: true
true
This is the main axis in which shifting is applied.
x
-axis for'top'
'top'
and'bottom'
'bottom'
placementsy
-axis for'left'
'left'
and'right'
'right'
placements
shift({
mainAxis: false,
});
shift({
mainAxis: false,
});
crossAxis
default: false
false
This is the cross axis in which shifting is applied, the opposite
axis of mainAxis
mainAxis
.
Enabling this can lead to the floating element overlapping
the reference element, which may not be desired and is often
replaced by the flip()
flip()
middleware.
shift({
crossAxis: true,
});
shift({
crossAxis: true,
});
limiter
default: no-op
This accepts a function 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.
import {shift, limitShift} from '@floating-ui/dom';
shift({
limiter: limitShift(),
});
import {shift, limitShift} from '@floating-ui/dom';
shift({
limiter: limitShift(),
});
This function itself takes options.
limitShift.mainAxis
default: true
true
Whether to apply limiting on the main axis.
shift({
limiter: limitShift({
mainAxis: false,
}),
});
shift({
limiter: limitShift({
mainAxis: false,
}),
});
limitShift.crossAxis
default: true
true
Whether to apply limiting on the cross axis.
shift({
limiter: limitShift({
crossAxis: false,
}),
});
shift({
limiter: limitShift({
crossAxis: false,
}),
});
limitShift.offset
default: 0
0
This will offset when the limiting starts. A positive number will start limiting earlier, while negative later.
shift({
limiter: limitShift({
// Start limiting 5px earlier
offset: 5,
}),
});
shift({
limiter: limitShift({
// Start limiting 5px earlier
offset: 5,
}),
});
This can also take a function, which provides the
Rect
Rect
s of each element to read their dimensions:
shift({
limiter: limitShift({
// Start limiting by the reference's width earlier
offset: ({rects, placement}) => rects.reference.width,
}),
});
shift({
limiter: limitShift({
// Start limiting by the reference's width earlier
offset: ({rects, placement}) => rects.reference.width,
}),
});
You may also pass an object to configure both axes:
shift({
limiter: limitShift({
// object
offset: {
mainAxis: 10,
crossAxis: 5,
},
// or a function which returns one
offset: ({rects, placement}) => ({
mainAxis: rects.reference.height,
crossAxis: rects.floating.width,
}),
}),
});
shift({
limiter: limitShift({
// object
offset: {
mainAxis: 10,
crossAxis: 5,
},
// or a function which returns one
offset: ({rects, placement}) => ({
mainAxis: rects.reference.height,
crossAxis: rects.floating.width,
}),
}),
});
…detectOverflowOptions
All of detectOverflow
’s options
can be passed. For instance:
shift({
padding: 5, // 0 by default
});
shift({
padding: 5, // 0 by default
});
If you find the padding does not get applied on the right side, see Handling large content.
Data
The following data is available in middlewareData.shift
middlewareData.shift
:
interface Data {
x: number;
y: number;
}
interface Data {
x: number;
y: number;
}
x
x
and y
y
represent how much the
floating element has been shifted along that axis. The values are
offsets, and therefore can be negative.