Introduction: The Challenge of UI Element Positioning
If you’ve spent more than five minutes building a web interface, you’ve likely fought the battle of the tooltip. You know the one. You want a little helpful bubble to appear right above a button when a user hovers over it. Sounds simple, right?
But then you start coding. You set position: relative on the button and position: absolute on the tooltip. It looks great—until you put the button inside a container with overflow: hidden. Suddenly, your beautiful tooltip is chopped off, decapitated by the boundaries of its parent. Or maybe the tooltip flips off the side of the screen on mobile devices.
For years, this has been the bane of our existence as frontend developers. We want things to "float" next to other things, but the DOM structure fights us every step of the way.
To solve this, we’ve historically turned to JavaScript. Libraries like Popper.js (now often used via Floating UI) became standard equipment in our toolbelts. They do the heavy math to calculate exactly where an element should sit on the screen, relative to another element, regardless of where they live in the HTML hierarchy.
But here’s the thing—relying on JavaScript for layout feels a bit... wrong. Layout is CSS's job. And finally, after years of wishing, the CSS Anchor Positioning API is here to reclaim that territory.
In this guide, we’re going to dive deep into this new API. We'll see if it’s finally time to say goodbye to our heavy JavaScript dependencies and embrace a native, performant future.
What is CSS Anchor Positioning API?
Let’s strip away the jargon for a second. At its core, the CSS Anchor Positioning API is a way to tell the browser, "Hey, see this element over here? I want to stick this other element right next to it."
The magic is that it breaks the traditional rules of absolute positioning.
Normally, if you use position: absolute, the element positions itself relative to its nearest positioned ancestor (usually a parent div with relative or absolute positioning). This meant your tooltip had to be nested inside the button, or you had to use JavaScript to calculate specific pixel coordinates.
With the Anchor API, you can link two completely separate elements in the DOM. You can have a button in your header and a tooltip at the very bottom of your <body> tag, and CSS can still glue them together perfectly.
It essentially creates a reference point—an anchor—that other elements can latch onto. It’s like giving your HTML elements a GPS tracker that other elements can follow.
Key Features and Syntax of the Anchor API
So, how do we actually use this thing? The syntax might look a little alien at first if you're used to standard CSS, but it follows a logical pattern.
There are two main players in this game:
- The Anchor: The element you want to point to (like a button).
- The Target: The element you want to position (like a tooltip).
1. Naming the Anchor
First, you have to give your anchor element a name. We use the anchor-name property for this. It looks like a CSS variable, starting with double dashes.
.my-button {
anchor-name: --save-btn;
}
2. Linking the Target
Next, you tell the target element which anchor to look for using position-anchor.
.my-tooltip {
position: absolute; /* This is still required! */
position-anchor: --save-btn;
}
3. Positioning with the anchor() Function
Finally, you use the anchor() function to set the coordinates. Instead of saying top: 10px, you say, "Put my top edge against the anchor's bottom edge."
.my-tooltip {
top: anchor(bottom);
left: anchor(center);
}
This is a game-changer because it moves the relationship logic out of the HTML structure and purely into the style layer.
How CSS Anchor Positioning Works (with examples)
Let’s build something real. Imagine we have a "Help" icon, and we want a popover to appear to the right of it.
The HTML Structure
Notice how the .info-popover isn't inside the button. It's a sibling. In the old days, this would make positioning a nightmare without JavaScript.
<div class="container">
<button class="help-icon">?</button>
<div class="info-popover">
This saves your current progress to the database.
</div>
</div>
The CSS Magic
Here is how we wire it up. We are going to define the button as the anchor, and then tell the popover to sit to the right of it, vertically centered.
/* 1. Define the Anchor */
.help-icon {
anchor-name: --help-trigger;
}
/* 2. Position the Target */
.info-popover {
position: absolute;
position-anchor: --help-trigger;
/* 3. usage of anchor() function */
/* align the left side of popover to right side of anchor */
left: anchor(right);
/* align the vertical center of popover to vertical center of anchor */
top: anchor(center);
/* Add some spacing */
margin-left: 10px;
}
That’s it. No event listeners calculating getBoundingClientRect(). No resize observers. Just declarative CSS.
Handling Overflow automatically
One of the coolest features is position-try. This tells the browser, "Try to put it on the right. But if it doesn't fit (like if the user is on a mobile phone edge), try putting it on the bottom instead."
.info-popover {
position-anchor: --help-trigger;
position-try-options: flip-block, flip-inline;
}
This mimics the "flipping" behavior that made libraries like Popper.js so essential.
Understanding Popper.js: Its Role and Strengths
To understand if we can replace Popper.js, we have to respect what it does. Popper.js (and its successor Floating UI) is a beast of a library in the best way possible.
It solved problems we didn't even know we had.
- Collision Detection: It knows when your tooltip is about to hit the edge of the viewport and intelligently moves it.
- Scrolling Containers: If your button is inside a scrolling div, Popper does the math to keep the tooltip attached to the button as you scroll, even if the tooltip is appended to the
<body>to avoidoverflow: hiddenclipping. - Virtual Elements: You can position a tooltip relative to a mouse cursor coordinate, not just a DOM element.
For a long time, if you were building a serious UI library—think Material UI or Bootstrap—you depended on Popper. It provided a level of polish that raw CSS simply couldn't match.
But adding JavaScript comes with a cost. There's the download size (even if small), the parsing time, and the runtime performance hit of recalculating positions every time the user scrolls or resizes the window.
Direct Comparison: Anchor API vs. Popper.js
Let’s break it down. Is the new kid on the block ready to take on the champion?
| Feature | CSS Anchor API | Popper.js (Floating UI) |
|---|---|---|
| Performance | Native speed. Runs on the compositor thread where possible. Zero JS bundle size. | JavaScript based. Fast, but requires main thread execution on scroll/resize. Adds to bundle size. |
| Setup | Declarative CSS. Simple syntax. | Imperative JavaScript setup. Requires initializing instances. |
| Responsiveness | Updates instantly with layout changes. | Reacts to events; might have a micro-delay on fast scrolls. |
| Browser Support | Limited. Currently Chrome/Edge heavy. Needs polyfills for Safari/Firefox (as of late 2024/early 2025). | Universal. Works everywhere JavaScript runs. |
| Complexity | Great for standard positioning and basic flipping. | Can handle extremely complex scenarios, like nested scrolling containers and virtual coordinates. |
The biggest takeaway? CSS Anchor Positioning is performant by default. Because the browser handles the layout calculations internally, you don't get that jagged "lag" where a tooltip drifts away from a button during a fast scroll before snapping back.
Use Cases Where Anchor API Shines
So, where should you use this right now?
1. Simple Tooltips and Toggles
If you have a simple "info" icon or a dropdown menu in a navigation bar, the Anchor API is perfect. It removes the need to import a JavaScript library for what should be a styling concern.
2. Footnotes and Sidenotes
Imagine clicking a footnote number in an article, and having the citation appear in the margin directly next to that line of text. The Anchor API makes this trivial.
3. Chart Annotations
If you are using HTML/CSS to draw charts (perhaps using CSS Grid Layout), you can anchor labels to specific data bars without calculating pixels manually.
4. Tutorial Walkthroughs
You know those "onboarding" flows that highlight a button and show a text box explaining it? Usually, these require heavy JS overlays. With Anchor Positioning, you can just point a description box at any element on the page effortlessly.
Potential Limitations and Browser Support
Here is the bucket of cold water. As exciting as this is, we have to talk about browser support.
As of the time of writing, the CSS Anchor Positioning API is available in Chromium-based browsers (Chrome, Edge, Opera). Firefox and Safari have shown interest and are working on implementations, but they aren't fully there yet for stable production use without fallbacks.
Limitations:
- Styling the Arrow: Popper.js has built-in logic to help position the little "arrow" triangle that points to the button. While you can do this in CSS, aligning it perfectly as the popover flips positions requires some clever math.
- Complex Interactivity: If you need your popover to do complex things when it collides with another specific element (not just the viewport edge), JavaScript might still be easier to manage.
Migration Strategy: When and How to Transition
Should you rip out Popper.js today? Probably not. But you should start preparing.
The best strategy right now is Progressive Enhancement. You can use CSS @supports to check if the browser handles anchor positioning.
@supports (anchor-name: --test) {
/* Use the fancy new CSS API */
.tooltip {
position-anchor: --btn;
top: anchor(bottom);
}
}
@supports not (anchor-name: --test) {
/* Fallback to old CSS or keep using JS classes */
/* Or perhaps simple absolute positioning that isn't as robust */
}
However, a more realistic approach for 2025 is to use a Polyfill. The team behind Floating UI (the successor to Popper) has actually released a polyfill for the CSS Anchor Positioning API. This is brilliant. It allows you to write the modern CSS syntax today, and the polyfill uses JavaScript to make it work in Safari and Firefox.
This effectively lets you write "future code" now. When the other browsers catch up, you just delete the polyfill script, and your CSS keeps working natively.
Steps to Transition:
- Audit your site: identifying simple popovers/tooltips.
- Experiment: Try replacing one instance with the Anchor API.
- Polyfill: Install the CSS Anchor Positioning polyfill.
- Test: verify behavior on Safari and Firefox.
Conclusion: The Future of UI Positioning
The CSS Anchor Positioning API is more than just a new feature; it’s a philosophy shift. It’s the web platform acknowledging that relationships between elements are a fundamental part of visual design, not just a side effect of the DOM tree.
Is it time to ditch Popper.js entirely? For simple projects targeting modern browsers, or if you are willing to use a polyfill? Yes. The performance wins and code simplicity are too good to ignore.
For complex, mission-critical applications that need to support older browsers without polyfill overhead? You might stick with Popper for a little longer. But the clock is ticking. The future is native, and it is anchored firmly in CSS.
Frequently Asked Questions
What browsers support the CSS Anchor Positioning API? Currently, support is strongest in Chromium-based browsers like Google Chrome, Microsoft Edge, and Opera. Firefox and Safari are in the process of implementing it. For production sites, it is highly recommended to use a polyfill or a fallback strategy.
Does CSS Anchor Positioning work with
overflow: hidden? Not exactly. If the anchor and target are inside a container withoverflow: hidden, the target will still be clipped. The solution is usually to place the target element higher up in the DOM (like directly in the<body>) and use the Anchor API to visually link it to the button deep inside the hidden container.
Can I use Anchor Positioning for animations? Yes! Since it uses standard CSS properties like
topandleft, you can transition these values. However, animating layout properties can be performance-intensive, so use with care.
Is this different from
position: sticky? Yes, very different.position: stickykeeps an element in the viewport based on scroll position relative to its parent. Anchor Positioning links an element's position to another specific element, regardless of scroll position or parent-child relationship.
Do I still need JavaScript for tooltips? You might still need a tiny bit of JavaScript to handle the interaction (like adding/removing a class to show or hide the tooltip on click), but you no longer need JavaScript for the positioning logic.