CSS Anchor Positioning Just Replaced Our Last JavaScript Library
Andika's AI AssistantPenulis
CSS Anchor Positioning Just Replaced Our Last JavaScript Library
For years, a certain type of JavaScript library has been a non-negotiable part of our frontend stack. You know the one: a clever, indispensable tool for positioning one element relative to another. Whether for tooltips, popovers, or dropdown menus, we relied on libraries like Popper.js or Floating UI to handle the complex calculations. But today, that changed. The native CSS Anchor Positioning API, which just landed in Chrome 125, is so powerful and elegant that it allowed us to completely remove our last major UI JavaScript dependency.
Let's be honest: positioning floating elements has always been a CSS pain point. We've all written brittle code to place a tooltip "just right," only to watch it break when the user scrolls or resizes the window. JavaScript libraries solved this by imperatively measuring the DOM and constantly updating element styles. It worked, but it came at a cost: increased bundle size, performance overhead from constant calculations, and another dependency to maintain. The new CSS Anchor Positioning API fundamentally changes this dynamic, moving layout logic from JavaScript back to the browser's rendering engine where it belongs.
The JavaScript Tethering Tax We All Paid
Before we dive into the solution, it's crucial to understand the problem we've been living with. The challenge of "tethering" one element to another is surprisingly complex. A tooltip, for example, needs to:
Appear next to its trigger element.
Reposition itself if the trigger element moves due to scrolling or layout shifts.
Flip to the other side if it runs out of viewport space.
Remain performant, even on complex pages.
JavaScript libraries like Popper.js became industry standards because they solved these problems robustly. They provided a powerful, imperative API to create a virtual link between an "anchor" element and a "floating" element. But this power came with what we call the "JavaScript Tethering Tax"—a series of trade-offs:
Performance Overhead: The library needs to run calculations on every scroll or resize event, which can lead to layout jank on heavy pages.
Bundle Size: Adding 5-10 kB (gzipped) for a single UI feature might seem small, but it adds up, impacting initial page load times.
Code Complexity: Your component logic becomes intertwined with the library's setup, state management, and cleanup methods, making the code more complex than it needs to be.
We accepted this tax because there was no native alternative. Until now.
What is CSS Anchor Positioning? A Declarative Revolution
The CSS Anchor Positioning API is a new set of CSS properties that allows you to declaratively tie the position of one element to another (the "anchor") directly in your stylesheet. Instead of telling the browser how to calculate the position with JavaScript, you simply tell it what the relationship should be. The browser's highly optimized rendering engine handles the rest.
This declarative approach is a paradigm shift. The browser now natively understands the spatial relationship between elements, automatically repositioning them with near-zero performance cost.
The anchor-name Property: Planting the Flag
The first step is to identify your anchor element. This is the element you want to position another element relative to, like a button that triggers a tooltip. You do this with the anchor-name property. The value must be a dashed-ident (like a CSS variable).
.tooltip-trigger{/* This element is now an anchor named --trigger */anchor-name:--trigger;}
By adding this one line, you've created a positional reference that other elements can use.
The position-anchor Property and anchor() Function: Tying the Knot
Next, you tell your floating element (e.g., the tooltip) which anchor to follow using the position-anchor property. Then, you use the new anchor() function within your positioning properties (top, left, right, bottom) to specify the exact relationship.
The anchor() function is incredibly powerful. You can reference the edges of the anchor element (anchor(top), anchor(left), anchor(bottom), anchor(right)) or its dimensions (anchor(width), anchor(height)).
.tooltip{/* This element must be absolutely positioned */position: absolute;/* Tie this element to the --trigger anchor */position-anchor:--trigger;/* Position my top edge to the anchor's bottom edge */top:anchor(bottom);/* Center my left edge with the anchor's center */left:anchor(center);}
And just like that, you have a tooltip that stays perfectly tethered to its trigger, no JavaScript required.
Our Use Case: Replacing Popper.js for Dynamic Tooltips
At our company, we used a Popper.js-based library for all our tooltips and dropdowns. It was a reliable workhorse, but a constant line item in our performance budget. We decided to refactor a complex tooltip component as our first test of the new CSS positioning API.
Before: The JavaScript Approach
Our old Tooltip component involved importing the library, creating an instance in a useEffect hook, passing in configuration objects, and meticulously managing cleanup to prevent memory leaks. The logic looked something like this:
Render the button and the tooltip div into the DOM.
Write separate logic to show/hide the tooltip by toggling a class or attribute.
On component unmount, call the destroy() method on the Popper instance.
This added about 7 kB to our component's bundle and required careful state management.
After: The Pure CSS Solution
The refactor was astonishingly simple. We removed the JavaScript library entirely and replaced all that logic with a few lines of CSS.
Here's our simplified implementation:
HTML:
<buttonclass="tooltip-trigger"> Hover Me
<divclass="tooltip"role="tooltip"> I am a CSS-powered tooltip!
</div></button>
CSS:
.tooltip-trigger{position: relative;/* For the show/hide mechanism */anchor-name:--my-trigger;}.tooltip{/* 1. Hide by default */opacity:0;transform:scale(0.9);transition: opacity 0.2s, transform 0.2s;/* 2. Set up anchor positioning */position: absolute;position-anchor:--my-trigger;/* 3. Position the tooltip below the anchor */top:anchor(bottom,8px);/* 8px gap */left:anchor(center);transform-origin: top center;/* 4. Add fallback positioning for unsupported browsers */@supportsnot(position-anchor:--my-trigger){top:100%;left:50%;transform:translateX(-50%);}}/* 5. Show on hover/focus */.tooltip-trigger:is(:hover,:focus-visible).tooltip{opacity:1;transform:scale(1);}
The result? We deleted over 100 lines of JavaScript and the entire library dependency. The component is now faster, simpler, and more maintainable. The browser handles all the edge detection and repositioning automatically.
Browser Support and The Path Forward
CSS Anchor Positioning is a cutting-edge feature. As of this writing, it is available in Chrome 125 and Edge 125. It is under active development in Safari and Firefox.
While full cross-browser support isn't here yet, you don't have to wait. You can start using it today with progressive enhancement. By using the @supports at-rule, you can provide the enhanced, anchor-based positioning for users on modern browsers while serving a simpler, good-enough fallback for others.
.my-popover{/* Basic fallback position */top:100%;left:0;/* Enhanced position for supported browsers */@supports(position-anchor:--anchor){position-anchor:--anchor;inset-area: bottom;/* A shorthand for common placements */}}
The CSS Anchor Positioning API is more than just a new feature; it's a fundamental shift in how we build dynamic UIs on the web. It addresses a long-standing limitation of CSS, providing a declarative, performant, and elegant solution to a problem we've been solving with JavaScript for over a decade.
By offloading complex positioning logic to the browser's rendering engine, we can build faster, lighter, and more resilient web applications. For our team, it was the final piece of the puzzle that allowed us to remove a significant JavaScript dependency, simplifying our codebase and improving performance in one fell swoop.
We are entering a new era of CSS-driven UI development. Now is the time to start experimenting. Check your analytics, and if a significant portion of your user base is on a supported browser, start enhancing your components.
What will you build first with the CSS Anchor Positioning API?
Created by Andika's AI Assistant
Full-stack developer passionate about building great user experiences. Writing about web development, React, and everything in between.