## The 47KB Library You No Longer Need
For over a decade, every web developer who needed a tooltip that didn't clip at the viewport edge reached for a JavaScript library. Floating UI. Popper.js. Tippy.js. Each one existed to solve the same problem: the browser had no native way to say "position this element relative to that element, and flip it if it overflows."
That problem is solved. In 2026, **CSS Anchor Positioning is fully supported across all major browsers** — Chrome, Firefox, Safari, and Edge. The spec that browsers spent three years implementing does natively what your 47KB positioning library did in JavaScript. And it does it better: no layout thrashing, no requestAnimationFrame, no ResizeObserver juggling. The browser handles overflow detection, viewport clipping, and automatic position flipping at the compositor level.
This is not a "can I use it yet?" situation. It is a "should I be using it already?" situation. The answer is yes.
---
## Section 1: What CSS Anchor Positioning Is
CSS Anchor Positioning is a native browser API for tethering one element's position to another using pure CSS. It solves the class of problems previously requiring JavaScript: placing a tooltip above a button, flipping a dropdown below when there is no space above, aligning a context menu to the right-click target.
**The three-property model:**
```css
/* 1. Declare the anchor */
.trigger {
anchor-name: --my-tooltip;
}
/* 2. Reference the anchor and position absolutely */
.tooltip {
position: absolute;
position-anchor: --my-tooltip;
/* 3. Use anchor() to set offsets relative to the anchor */
bottom: calc(anchor(top) + 8px); /* 8px above the trigger */
left: anchor(center);
translate: -50% 0; /* center-align horizontally */
}
```
That is the complete implementation of a centered tooltip above a button. No JavaScript. No library. No ResizeObserver.
**The `anchor()` function** takes a side keyword (`top`, `bottom`, `left`, `right`, `center`, `start`, `end`) and returns the corresponding coordinate of the anchor element in the page's coordinate space. You use it anywhere you would use a length value in a position property.
**`position-anchor`** declares which anchor the floating element is attached to. It references the `anchor-name` value with a CSS custom property syntax (`--name`).
**`position`** must be `absolute` or `fixed`. Anchor positioning only applies to absolutely-positioned elements — the same constraint that made JavaScript libraries necessary in the first place.
---
## Section 2: The `@position-try` Rule — Automatic Overflow Handling
The `@position-try` rule is where CSS Anchor Positioning becomes genuinely superior to most JavaScript implementations. It is the native equivalent of Floating UI's `autoPlacement` and `flip` middleware — but declarative and zero-cost.
```css
/* Default position: above the trigger */
.tooltip {
position: absolute;
position-anchor: --my-trigger;
bottom: calc(anchor(top) + 8px);
left: anchor(center);
translate: -50% 0;
position-try-fallbacks: --below, --right, --left;
}
/* Fallback 1: below the trigger */
@position-try --below {
bottom: auto;
top: calc(anchor(bottom) + 8px);
}
/* Fallback 2: to the right */
@position-try --right {
bottom: auto;
left: calc(anchor(right) + 8px);
translate: 0 -50%;
top: anchor(center);
}
/* Fallback 3: to the left */
@position-try --left {
bottom: auto;
right: calc(anchor(left) + 8px);
left: auto;
translate: 0 -50%;
top: anchor(center);
}
```
The browser tries each `@position-try` block in order and uses the first one where the positioned element fits entirely within the viewport. No JavaScript scroll listeners. No requestAnimationFrame. No layout calculations. The browser does it at paint time.
This is Floating UI's entire `autoPlacement` + `flip` feature set, in CSS.
---
## Section 3: 5 Common UI Patterns — Before and After
### Pattern 1: Tooltip
**Before (Floating UI):**
```typescript
// ~15 lines of JS + 47KB library
import { computePosition, flip, shift, offset } from '@floating-ui/dom';
computePosition(trigger, tooltip, {
placement: 'top',
middleware: [offset(8), flip(), shift({ padding: 8 })]
}).then(({ x, y }) => {
Object.assign(tooltip.style, { left: `${x}px`, top: `${y}px` });
});
```
**After (CSS Anchor Positioning):**
```css
.trigger { anchor-name: --tooltip-anchor; }
.tooltip {
position: absolute;
position-anchor: --tooltip-anchor;
bottom: calc(anchor(top) + 8px);
left: anchor(center);
translate: -50% 0;
position-try-fallbacks: --tooltip-below;
}
@position-try --tooltip-below {
bottom: auto;
top: calc(anchor(bottom) + 8px);
}
```
Zero JavaScript. Full overflow handling.
---
### Pattern 2: Dropdown Menu
```css
.dropdown-trigger {
anchor-name: --dropdown;
}
.dropdown-menu {
position: fixed; /* fixed keeps it above sticky headers */
position-anchor: --dropdown;
top: calc(anchor(bottom) + 4px);
left: anchor(left);
min-width: anchor-size(width); /* match trigger width */
position-try-fallbacks: --dropdown-above;
}
@position-try --dropdown-above {
top: auto;
bottom: calc(anchor(top) + 4px);
}
```
`anchor-size(width)` is a companion function that returns the anchor element's dimension — perfect for ensuring a dropdown is at least as wide as its trigger.
---
### Pattern 3: Context Menu (Right-Click)
```css
.context-menu {
position: fixed;
position-anchor: --context-anchor;
top: anchor(top);
left: anchor(right);
position-try-fallbacks: --context-left, --context-below-right;
}
@position-try --context-left {
left: auto;
right: calc(100% - anchor(left));
}
@position-try --context-below-right {
top: anchor(bottom);
left: anchor(left);
}
```
In JavaScript, you set the `anchor-name` on a zero-size element at the mouse cursor position, giving you a click-position anchor with full CSS overflow handling.
---
### Pattern 4: Popover with Arrow
Combine CSS Anchor Positioning with the HTML Popover API for a zero-JavaScript disclosure pattern:
```html
Open
Popover content here
```
```css
[popovertarget] { anchor-name: --popover-trigger; }
[popover] {
position: absolute;
position-anchor: --popover-trigger;
top: calc(anchor(bottom) + 12px);
left: anchor(center);
translate: -50% 0;
}
.popover-arrow {
position: absolute;
bottom: 100%;
left: 50%;
translate: -50% 0;
/* triangle CSS */
}
```
Toggle behavior, positioning, and overflow handling — entirely native.
---
### Pattern 5: Select Dropdown (Custom)
```css
.custom-select { anchor-name: --select; }
.custom-options {
position: fixed;
position-anchor: --select;
top: calc(anchor(bottom) + 2px);
left: anchor(left);
width: anchor-size(width);
max-height: 240px;
overflow-y: auto;
position-try-fallbacks: --select-above;
}
@position-try --select-above {
top: auto;
bottom: calc(anchor(top) + 2px);
}
```
---
## Section 4: Angular Integration
In Angular, CSS Anchor Positioning works with zero framework-specific code — it is pure CSS applied to your template elements. But there are patterns that make it ergonomic in Angular components.
**Using `anchor-name` with dynamic values via CSS custom properties:**
```typescript
@Component({
template: `
{{ label }}
{{ content }}
`
})
export class AnchoredTooltipComponent {
@Input() id = '';
@Input() label = '';
@Input() content = '';
open = false;
}
```
This pattern allows multiple instances of the component on a page — each with a unique `anchor-name` scoped to its `id` — without any coordinate calculations.
**Combining with Angular's `@defer` for lazy tooltip content:**
```html
Hover me
@defer (on hover) {
}
```
The tooltip content is deferred until hover, and the positioning is handled entirely by CSS after it renders.
---
## Section 5: When to Still Use Floating UI
CSS Anchor Positioning handles 90% of tooltip and dropdown cases. The remaining 10% where JavaScript libraries still add value:
| Use Case | CSS Anchor Positioning | Floating UI |
|---|---|---|
| Standard tooltips | ✅ Native CSS | Not needed |
| Dropdowns and selects | ✅ Native CSS | Not needed |
| Context menus | ✅ Native CSS | Not needed |
| Popovers | ✅ Native CSS + Popover API | Not needed |
| Virtual list tooltips | ❌ Needs JS anchor | ✅ Use Floating UI |
| Canvas-relative positioning | ❌ No DOM anchor | ✅ Use Floating UI |
| Complex middleware chains | ❌ Limited fallbacks | ✅ Use Floating UI |
| Drag-and-drop tether | ❌ Dynamic anchors limited | ✅ Use Floating UI |
For the vast majority of UI component libraries and product interfaces, CSS Anchor Positioning is the correct choice in 2026.
---
## Section 6: Migration Checklist
If you are migrating an existing codebase from Floating UI or Popper.js:
1. **Audit tooltip/dropdown usage** — identify which are standard (trigger → float) vs. complex (virtual, canvas, drag)
2. **Add `anchor-name` to trigger elements** — replace JavaScript anchor references with CSS declarations
3. **Replace `computePosition()` calls** with CSS `position-anchor` + `anchor()` properties
4. **Replace `flip()` middleware** with `@position-try` fallback blocks
5. **Replace `shift()` middleware** with `overflow: clip` or `inset` constraints on the floating element
6. **Remove `update()` calls** — CSS Anchor Positioning is automatically reactive to layout changes
7. **Test overflow scenarios** — verify `@position-try` fallbacks work at viewport edges
8. **Measure bundle size reduction** — expect 40-100KB+ reduction for most projects
---
## Conclusion: CSS Won This Round
CSS Anchor Positioning is not an incremental improvement. It is the browser finally solving a class of problems that forced an entire ecosystem of JavaScript libraries into existence. Those libraries were always a workaround. They added runtime overhead, bundle size, event listener management, and ResizeObserver complexity to solve a layout problem that should have been CSS's job.
In 2026, it is CSS's job. The platform has caught up. The correct default for tooltips, dropdowns, popovers, and context menus is now CSS Anchor Positioning — zero JavaScript, no library, full overflow handling built into the browser.
**If you installed Floating UI for tooltips, you can uninstall it now.**