Chimezie Innocent I am Chimezie, a software developer based in Nigeria. I am highly skilled in HTML, CSS, and JS to build web-accessible and progressive apps. I'm also skilled with React for web, React Native for Android apps, and Tailwind CSS. I write technical articles, too.

Popper vs. Floating UI

6 min read 1870

Popper Vs. Floating UI

The CSS float property specifies whether an element should float to the left, right, or not at all, and allows us to take an element, remove it from the normal flow of a page, and position it to the left or right of its parent element.

When this happens, all the other elements on the page flow around the floated element. Today, however, we have tools that make positioning these floating elements (in this case, called poppers) easier while intelligently keeping them in view.

While there are many positioning tools and libraries, Floating UI and Popper remain the most popular and most used. Hence, the need to answer these questions:

  1. Which library is best to use?
  2. Which library provides more support?
  3. Which library is easier to use?

In this article, we will look at these two libraries, what makes them different, and which one is best to use.

Introduction to Popper

Before Popper was created in 2006, Tether was the open source solution to position floating elements but was superseded by Popper.

Popper is a lightweight library that aims to provide a reliable and extensible positioning engine to ensure all popper elements are positioned in the right place These popper elements include tooltips, popovers, dropdowns, menus, and more.

Popper also focuses on compatibility, bundle size, and a more modern API.

Introduction to Floating UI

Floating UI is an upgrade of Popper; it is an evolution of libraries like Popper v2 and Tether with a more modern API.

Federico Zivolo, the creator of Popper and co-maintainer of Floating UI, notes that even though Popper v2 might still be available and working, Floating UI was created to replace it.

One distinct factor that makes Floating UI better than Popper is that while Popper only runs on the web using the DOM, Floating UI supports both the web, React Native, Canvas, and more.

We made a custom demo for .
No really. Click here to check it out.

Since Floating UI is an upgrade to Popper, let us see what makes them different.

Why not use pure CSS?

Before we go into the differences between Floating UI and Popper, you might wonder why you should learn how to use a new tool for what you can do with your pure CSS.

While you’re correct—you can use pure CSS to do the same things Popper and Floating UI can—there are some downsides to using pure CSS instead of using Floating UI or Popper.

No flipping

Vanilla CSS poppers do not flip to a different placement or position to fit better in view when necessary. You can achieve this using JavaScript to transform the poppers, but you cannot achieve this with CSS only.

Popper and Floating UI automatically flip poppers to fit in view as best as possible. Using Floating UI, let’s see how we can automatically flip our poppers.

In React, add this code to an App.js file; the paragraph will be our reference element while the tooltip will be our popper:

// App.js

import React from 'react';
import { computePosition, flip } from '@floating-ui/dom';
import './style.css';

const App = () => {
const paragraph = document.querySelector('.paragraph');
const tooltip = document.querySelector('.tooltip');
computePosition(paragraph, tooltip, {
    placement: 'top',
    middleware: [ flip() ]
}).then(({ x, y }) => {
    Object.assign(tooltip.style, {
       left: `${x}px`,
       top: `${y}px`
    });
});
    return (
        <div>
            <p className="paragraph"> Hover over me! </p>
            <div className="tooltip">
                This is a tooltip that shows extra info
            </div>
        </div>
    );
};
export default App;

In a style.css file, add the code below:

// style.css

body {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
.paragraph {
    margin: 60px 0 0 60px;
    font-size: 14px;
    position: absolute;
}
.tooltip {
    background: black;
    color: white;
    font-size: 16px;
    padding: 6px;
    border-radius: 5px;
    pointer-events: none;
    position: absolute;
}

Floating UI has a middleware called flip, and it automatically translates or changes the popper placement to the opposite axis or direction when it is out of our viewport, so we don’t need to manually change it ourselves.

Flip() is used when a popper is placed at the top or bottom of the reference element.

That means if we placed our popper on top of the reference element, when there is no space above the reference element to display the popper, Floating UI automatically changes the placement to the bottom and vice versa.

So, here’s what our app looks like before we added Flip():

App Without Flip, Button Positioned In Top Left

And then, here’s our after we add Flip():

App Using Flip, Adding A Tooltip In Top Left Corner

Clipping and overflow issues

Pure CSS poppers are not prevented from overflowing clipping boundaries, such as the viewport. They will get partially cut off or overflow if they’re near the edge since there is no dynamic positioning logic.

But, when using Popper and Floating UI, your popper will always be positioned in the right place without manually adjusting, therefore ensuring the popper is always kept inside the viewport.

Unlike Flip() that works vertically, Shift() works horizontally along the x-axis. This will always ensure the popper doesn’t overflow outside our viewport.

To import Shift() from the Floating UI package, add the following:

// App.js

import { computePosition, shift } from '@floating-ui/dom';

computePosition(paragraph, tooltip, {
    middleware: [ shift() ]
})

Here’s what our app looks like before we added Shift():

App Before Adding Shift

And then with Shift() added:

App After Adding Shift

Slower development cycle

When using pure CSS to position popper elements, they must be carefully placed to consider overflow on all screen sizes and positioned over the reference element correctly, which can be time-consuming.

With Popper and Floating UI, you can place your elements anywhere and they will position correctly without needing to consider different screen sizes, layouts, and so on.

This massively speeds up development time because the work is automatically offloaded to Popper and Floating UI.

Comparing Floating UI to Popper

Cross-platform functionalities

As previously mentioned, Floating UI is cross-platform. While Popper only supports the web, Floating UI supports mobile, Canvas, and WebGL with the right interface logic. In fact, Floating UI runs on any JavaScript environment.

Library size

Popper is a lightweight library meaning that it is small in size at about 3kb. Floating UI, on the other hand, is only 600 bytes, which makes it even smaller in size.

Tree-shakeable

Tree-shaking is the removal of unused codes from a bundle during bundling for production.

Popper is not tree-shakeable by default. To leverage the tree-shaking feature, you must use Popper Lite:

import { createPopper } from "@popperjs/core/lib/popper-lite"

Floating UI is modular by default hence it is tree-shakeable. Also, new features are tree-shaken away if you don’t want to use them.

Placements

Placement is an option that shows where the poppers are placed, meaning the popper can be placed either at the top, bottom, left, or right of the reference element.

The auto-placement automatically places the popper at the side with more space, and Popper offers auto-placement as one of the placement options while Floating UI offers it as a modifier:

// Popper
import { createPopper } from "@popperjs/core"

createPopper(referenceElement, floatingElement, {
    placement: 'auto'
})

// Floating UI
import { computePosition, autoPlacemnt } from "@floating-ui/dom"

computePosition(referenceElement, floatingElement, {
    middleware: [ autoPlacement()]
})

Overall features

Floating UI supports more features than Popper like the size and inline middlewares. The size middleware changes the size of the floating element, ensuring it doesn’t overflow the available space. This means that the floating element will always fit into the available space:

import { computePosition, size } from '@floating-ui/dom';

computePosition(referenceElement, floatingElement, {
    middleware: [ size({ padding: 5 })]
})

The inline middleware allows the positioning of the floating element on an inline reference element. When the reference element spans over another line, the inline middleware allows the floating element to properly position on the inline reference element.

Improved extensibility

Popper is built with extensibility in mind, yet, writing modifiers is still difficult because you need to check the data of other modifiers to write the correct logic.

To write an offset modifier in Popper, we do so with the following:

// Popper
import { createPopper } from "@popperjs/core"

createPopper(referenceElement, floatingElement, {
    placement: "top",
    modifiers: [{
        name: "offset",
        options: {
            offset: [0, 7]
        }
    }]
})

To write another modifier like flip, we must first check the data of offset before writing the flip modifier:

// Popper
import { createPopper } from "@popperjs/core"

createPopper(referenceElement, floatingElement, {
    placement: "top",
    modifiers: [{
        name: "offset",
        options: {
            offset: [0, 7]
        }
    }, name: "flip",
       options: {
            fallbackPlacements: ["top", "bottom"]
        }
    ]
})

With Floating UI, it is easier to write modifiers because you only need to arrange the middlewares properly since you control the order of the middleware array, making it more extensible:

// Floating UI
import { computePosition, shift, flip, offset } from "@floating-ui/dom"

computePosition(refrenceElement, floatingElement, {
    middleware: [ offset(), flip(), shift() ]
})

//Note: Offset must always be at the beginning of the array while hide and arrow must always be at the end

Strongly typed by default

Floating UI is built with TypeScript, hence it leverages the benefits of TypeScript like readability, type-check, predictability of the modifiers, and so on.

Popper, however, is built with Flow and is loosely typed by default, which means modifiers are not strictly type-checked. This means that modifiers’ data type errors are not spotted early except during runtime, making it error-prone.

TypeScript checks for data types and spots errors in the data types that change. Popper is not built that way, so the modifiers types are not checked early. The problem with this is that you will only spot the error at runtime/execution.

Predictability

Since Floating UI is written in TypeScript, it makes it more predictable than Popper.

That means everything stays the way it was initially defined; the middlewares are not enabled by default and you don’t need to preconfigure any middleware but can instead add them when you need them, unlike in Popper, where the middlewares are enabled by default.

Floating UI and Popper offers middlewares like the offset, arrow, shift, flip, and so on. To use these middlewares in Floating UI, you must import and use them because they are not enabled by default:

// Floating UI
import { computePosition, shift, flip, offset } from "@floating-ui/dom"

computePosition(refrenceElement, floatingElement, {
    middleware: [ offset(), flip(), shift() ]
})

In Popper, however, these middlewares are already enabled by default:

// Popper
import { createPopper } from "@popperjs/core"

createPopper(referenceElement, floatingElement, {
    modifiers: [{
        name: "offset",
        options: {
            offset: [0, 7]
        }
    }]
})

Future usability

Popper is being kept in a low maintenance mode, meaning maintenance will be low in frequency, so it’s currently unclear if new features will be added in the near future.

Much work, however, has gone into Floating UI to make it the best and easiest-to-use solution in the positioning space.

Conclusion

We have seen why using libraries like Floating UI and Popper to position our floating elements is better than using just vanilla CSS.

Floating UI is the evolution of Popper v2 to replace Popper and make it more cross-platform compatible. Sadly, there are few tutorials and fewer to no videos on Floating UI, so only the documentation is available to learn how to use it.

However, Popper has been used for quite a long time, and thus more tutorials and community support should you run into a problem.

Yet, for your use case, you should go for Floating UI because it offers more advantages. Not only is it easier to use, but you can use it with React, Vue, or even vanilla JavaScript to position your floating elements on the web. You can also use it with React Native to position floating elements on mobile.

Gracias!

Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.https://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web and mobile apps — .

Chimezie Innocent I am Chimezie, a software developer based in Nigeria. I am highly skilled in HTML, CSS, and JS to build web-accessible and progressive apps. I'm also skilled with React for web, React Native for Android apps, and Tailwind CSS. I write technical articles, too.

2 Replies to “Popper vs. Floating UI”

Leave a Reply