Learn how to migrate from Popper v2 to Floating UI.
Rebranding: The library was rebranded as it offers more packages and functionality, like the new React package that provides interactions, while Popper only ever offered positioning.
New API: The goal of the new API was to make Floating UI lower-level and act more like CSS in which you progressively add properties to achieve the desired positioning behavior, without pre-configuring anything.
In addition, we wanted to make the configuration more ergonomic, the library smaller and fully tree-shakeable (so new features don’t bloat bundles if unused), and also wanted to support React Native/Canvas as they had been requested, which is now supported.
Different, but familiar: Floating UI forked Popper 2 and shares a lot of similarities. While the main external positioning function changed, many other parts of the API are similar.
- The order of arguments and types of the positioning function are practically identical.
strategyare the same, passed as a third argument options object.
middlewarein Floating UI is conceptually similar to
modifiersfrom Popper 2.
- Options passed to middleware have very similar configuration as
Popper 2, and APIs like
detectOverflowand virtual elements are almost identical.
First thing’s first, uninstall
@popperjs/core and install
Popper applied styles and added modifiers for you by default. Floating UI on the other hand is completely bare bones — you add what you need with nothing pre-configured.
In Popper, you called
createPopper() like so and it would
place the popper element at the bottom for you automatically.
Floating UI does not apply styles or add modifiers (now more generically called middleware) for you. Instead it’s pure and only returns data that you can use as you please.
Set up the initial styles on the floating element in your CSS:
Then, apply the coordinates using the positioning data resolved by the function:
Read more about
computePosition() is not stateful, it only positions your
Popper added listeners automatically to update the position on scroll and resize. In Floating UI, you add this yourself, and it’s much more explicit that it needs to be cleaned up:
Floating UI also adds
ResizeObserver listeners by
default, unlike Popper, handling an additional update edge case.
Read more about
Floating UI honors the
placement you passed in and does
not modify it by default:
Even if the floating element will overflow the top of the screen, it will still be placed and anchored there.
If you’d like to directly match Popper’s default behavior to
prevent collisions, add in
limitShift() in the following order:
Unlike Popper 2, the order of the array matters and is not adjusted for you. The Middleware page explains the concept in detail. Essentially, if you place one of the middleware before or after another, the positioning result can change. This helps enable full control as sometimes you want different behavior based on the ordering.
preventOverflow modifier from Popper is now called
This is because technically many modifiers in Popper 2 “prevented
overflow”, which does not describe what it is actually doing
You’ll hopefully notice the API is much more ergonomic at the point of the function call.
A lot of the options passed in to middleware options are similar or the same as Popper 2. To learn about their options, you can read their pages on the sidebar on the left.
In Popper you could add a
inside your popper and it’d automatically be picked up and
As Floating UI is pure, you now handle these styles yourself, and
you always pass an element in manually. You can read more about
this on the
arrow middleware page.
In Popper 2, this was part of
flip but now it’s separate and is
no longer a string option for
detectOverflow() must now be called with the
await keyword before it but accepts the same options
as Popper 2 with minor differences.
If you think something is missing or are confused, you can open a Discussion on the GitHub repo and we’ll try to improve this page.