CSS Anchor Positioning Replaces JavaScript Libraries

CSS Anchor Positioning is now production-ready across all major browsers, enabling tooltips, popovers, and floating UI without JavaScript libraries. Learn how to replace Floating UI with pure CSS anchor() and @position-try for smaller bundles and better performance.

Share
Illustration of CSS anchor positioning replacing JavaScript libraries for UI tooltips and floating elements

CSS Anchor Positioning Replaces JavaScript Libraries for Tooltips, Popovers, and Dynamic UI

For years, frontend developers have reached for a familiar pattern whenever they needed a tooltip, dropdown menu, or floating card: grab a JavaScript positioning library. Headless UI, Floating UI, Popper.js — these tools have been the backbone of dynamic positioning on the web since before frameworks even existed. They compute coordinates, handle viewport clipping, and fire on scroll events with varying degrees of efficiency.

That era is ending. CSS Anchor Positioning is now production-ready across all major browsers, and it does everything those libraries do — without a single line of JavaScript or a package.json dependency.

What Is CSS Anchor Positioning?

The CSS Anchor Positioning API lets you position one element relative to another using pure CSS. Instead of computing positions in JavaScript and applying top and left styles dynamically, you declare a relationship between an anchor element and a positioned element directly in your stylesheet.

The core mechanism uses the anchor() function as a value for inset properties. You name an anchor with position-anchor, then reference it from any descendant using top: anchor(my-anchor top). The browser resolves this to an actual pixel value during layout, updating automatically when the anchor moves.

Here is a minimal tooltip example:

.tooltip-trigger {
  position: relative;
  position-anchor: --trigger;
}

.tooltip {
  position: absolute;
  top: anchor(--trigger bottom);
  left: anchor(--trigger center);
  offset-block-end: 0.5rem;
  offset-inline-start: -50%;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.tooltip-trigger:hover + .tooltip {
  opacity: 1;
}

The position-anchor property on the trigger marks it as a reference point. The tooltip then uses anchor(--trigger bottom) to place its top edge at the bottom of the trigger, horizontally centered. This is declarative — no event listeners, no recalculation on scroll, no reflow thrashing.

Browser Support Is Now Complete

This is what makes anchor positioning different from previous CSS proposals that languished in experimental limbo. As of early 2026, full support spans every major browser engine:

  • Chrome 125+ — stable since May 2024
  • Edge 125+ — Chromium-based, same timeline
  • Firefox 147+ — enabled by default since January 2026
  • Safari 26+ — implementation complete and shipped

All four engines now support the full spec, including @position-try for fallback positioning when an element would overflow its container. This is no longer a progressive enhancement to consider — it is baseline.

Real-World Use Cases Beyond Tooltips

While tooltips are the canonical example, anchor positioning unlocks several patterns that previously required JavaScript:

1. Dropdown Menus and Popovers

A dropdown positioned below a button, flipping above when near the viewport bottom, used to require a library with dozens of edge-case handlers:

.dropdown-trigger {
  position-anchor: --dd;
}

.dropdown-panel {
  position: absolute;
  top: anchor(--dd bottom);
  left: anchor(--dd center);
  offset-inline-start: -50%;
  @position-try {
    offset-block-end: auto;
    offset-block-start: -1rem;
  }
}

The @position-try block tells the browser: if the dropdown would overflow below the viewport, flip it above the trigger instead. Pure CSS. No JavaScript measurement.

2. Connector Lines Between Elements

Data visualization and annotation UIs often need lines or arrows connecting two elements. Anchor positioning resolves this naturally:

.chart-label {
  position-anchor: --label;
}

.chart-line::before {
  left: anchor(--label right);
  width: calc(anchor-size(--label width) + 2rem);
}

The anchor-size() function gives you the dimensions of the anchor element, enabling dynamic line widths that adapt when labels resize.

3. Floating Action Buttons and Sticky Cards

When a card or floating panel needs to track another element across scrolling content — like a price summary following a product thumbnail in an e-commerce layout — anchor positioning eliminates the scroll listener entirely.

Migration Strategy: Drop-in Replacement for Existing Libraries

If your project already uses Floating UI or Popper.js, migrating is straightforward. The mental model maps directly:

  • createPopper(reference, floating)position-anchor + anchor()
  • Middleware for viewport clipping → @position-try blocks
  • useFloating({ placement: 'top' })top: anchor(ref bottom)
  • update() on scroll → automatic by the browser

The migration path is not all-or-nothing. You can progressively replace library usage component by component, keeping the fallback for browsers that have not yet shipped support — though with full baseline coverage in 2026, polyfills are largely unnecessary.

Performance Implications

JavaScript-based positioning libraries introduce layout thrashing through repeated measurements. Even optimized libraries like Floating UI use getBoundingClientRect() and schedule updates via requestAnimationFrame. Anchor positioning moves all of this into the browser's layout engine, where it runs during the normal style calculation phase.

The result is a measurable reduction in main-thread work. For pages with many floating elements — dashboards, data tables with inline editors, complex forms — this translates to smoother interaction and lower CPU usage, especially on mobile devices where every millisecond matters.

Caveats and Gotchas

No feature is without trade-offs. Anchor positioning has a few limitations worth knowing:

  • Same-container constraint: The positioned element must be a descendant of the anchor's container (or within the same stacking context). Cross-root anchoring requires anchor-scope, which is still in development.
  • No diagonal offsets yet: You can anchor to edges and corners, but diagonal positioning requires combining multiple inset properties with calc().
  • Debugging: DevTools support for visualizing anchor relationships exists in Chrome and Firefox but is less polished than inspecting computed JavaScript positions.

The Bigger Picture

CSS Anchor Positioning is part of a broader shift: the browser doing more of what JavaScript frameworks have historically handled. Alongside features like CSS Container Queries, scroll-driven animations, and :has(), anchor positioning represents the completion of CSS's evolution from presentation-only to layout-aware.

For frontend engineers, this means fewer dependencies, smaller bundles, and simpler code. For teams building design systems, it means a single source of truth for positioning logic — your stylesheet, not a third-party package with its own update cycle and breaking changes.

The JavaScript libraries are not dead tomorrow. But the writing is on the wall: anchor positioning gives you everything those tools provide, declaratively, performantly, and natively. The question is no longer whether to adopt it — it is how fast you can start.