loke.dev
Header image for Stop Calculating Offsets: CSS Anchor Positioning is Finally Making Your UI Libraries Obsolete

Stop Calculating Offsets: CSS Anchor Positioning is Finally Making Your UI Libraries Obsolete

A deep dive into why tethering elements to each other no longer requires a 20kb JavaScript dependency or complex resize observers.

· 4 min read

If you’ve ever spent four hours debugging why a tooltip is hovering 20 pixels to the left of where it should be because a parent container had position: relative, you know that tethering elements in CSS has historically been a nightmare. We've been leaning on heavy JavaScript libraries to do basic geometry for a decade, and frankly, our bundles are tired.

The Math We Never Wanted to Do

Before now, if you wanted to pin a dropdown menu to a button, you basically had two choices:
1. Use position: absolute and pray the parent nesting never changed.
2. Ship a library like Popper.js or Floating UI.

These libraries are brilliant, but they’re solving a problem that shouldn't exist. To keep a popup "attached" to a trigger, these scripts have to listen for scroll events, resize events, and layout shifts, then manually recalculate top and left values using getBoundingClientRect(). It’s a lot of overhead for something that feels like it should be a native layout concern.

Enter the Anchor

The CSS Anchor Positioning API changes the mental model entirely. Instead of calculating coordinates, you simply give an element a name and tell another element to "stick" to it.

Here is the gist of how it works. First, you define the anchor (the reference point):

.anchor-button {
  anchor-name: --my-button;
}

Then, you tell the positioned element (the tooltip or menu) which anchor to follow:

.tooltip {
  position: fixed;
  position-anchor: --my-button;
  
  /* Stick the top of the tooltip to the bottom of the button */
  top: anchor(bottom);
  left: anchor(center);
  transform: translateX(-50%);
}

The browser handles the math. If the page scrolls, the browser moves the tooltip. If the window resizes, the browser moves the tooltip. No JavaScript execution, no main-thread jank, and zero resize observers.

Handling the "Overflow" Headache

One of the biggest pain points with traditional tooltips is the overflow: hidden trap. You have a button inside a sidebar with overflow: hidden, and your tooltip gets clipped because it’s a child of that sidebar.

To fix this, we usually teleport the tooltip to the <body> using a React Portal or similar logic. But then you lose the CSS context.

Anchor positioning solves this by allowing the anchored element to be anywhere in the DOM. As long as the anchor name is unique and visible, you can place your tooltip at the very bottom of your HTML, and it will still find its anchor and hover precisely where it belongs.

"What if it goes off-screen?"

This is where the magic really happens. Usually, "collision detection" is the part where you'd definitely need JavaScript. If a tooltip is supposed to be above a button but the button is at the top of the screen, the tooltip should flip to the bottom.

CSS now has @position-try to handle this logic:

.tooltip {
  position: fixed;
  position-anchor: --my-button;
  
  /* Define the preferred position */
  top: anchor(bottom);
  
  /* Tell it what to try if it overflows */
  position-try-options: --flip-v;
}

@position-try --flip-v {
  bottom: anchor(top);
  top: auto;
}

You can even use built-in keywords like flip-block or flip-inline to let the browser automatically calculate the mirror image of your positioning if space runs out. It’s remarkably smart.

The Catch (There's always one)

Before you go deleting node_modules/floating-ui, we need to talk about browser support. As of today, this is primarily a Chromium feature (Chrome and Edge 125+). Firefox and Safari are lagging behind, though it is officially on their radar.

I wouldn't ship this to a high-traffic production site without a fallback just yet, but for internal tools, Electron apps, or progressive enhancement, it's ready to go.

Why I’m Excited

I’m tired of "Layout via JavaScript." Every time we move a layout responsibility back to the CSS engine, we get better performance and more resilient code.

The Anchor Positioning API feels like the final piece of the UI puzzle. Between this and the <dialog> element, the "Standard UI Component" kit is finally becoming a reality. We're moving toward a web where you don't need a 20kb dependency just to show a "Help" bubble on hover—and that’s a win for everyone’s lighthouse scores.