🚀AdvancedAdvanced Layout

CSS Anchor Positioning

Position elements relative to other elements anywhere in the DOM using the CSS Anchor Positioning API, replacing complex JavaScript calculations.

Overview

CSS Anchor Positioning lets you position one element (the positioned element) relative to any other element (the anchor) in the DOM, not just its nearest positioned ancestor. This solves the long-standing problem of tooltips, popovers, and dropdowns: they must be in the top-level stacking context (for z-index) but visually attached to a button anywhere in the page. ```css /* Step 1: name the anchor */ .my-button { anchor-name: --btn-anchor; } /* Step 2: attach the tooltip to the anchor */ .tooltip { position: absolute; position-anchor: --btn-anchor; /* Position using anchor() function */ top: anchor(bottom); /* tooltip top = anchor bottom */ left: anchor(center); /* tooltip left = anchor center */ transform: translateX(-50%); } ``` **anchor() function values:** - `anchor(top)`, `anchor(bottom)`, `anchor(left)`, `anchor(right)` - `anchor(center)` midpoint of the axis - `anchor(self-start)`, `anchor(self-end)` **Automatic flipping with position-try:** ```css .tooltip { position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline; } ```

Key Points

  • •anchor-name: --name sets the anchor identifier on the reference element
  • •position-anchor: --name connects the positioned element to its anchor
  • •anchor() function returns a coordinate from the anchor element
  • •The positioned element can be anywhere in the DOM, not just inside the anchor
  • •position-try-fallbacks enables automatic repositioning when the preferred position overflows
  • •anchor-size() returns the width or height of the anchor element
  • •Works with top-layer elements (popover, dialog) that need visual attachment
  • •Supported in Chrome 125+ (behind flag in earlier versions)

Examples

Basic tooltip attached to a button

/* The button is the anchor */
.tooltip-trigger {
  anchor-name: --tooltip-anchor;
  position: relative; /* for inert fallback */
}

/* The tooltip is positioned relative to the anchor */
.tooltip {
  position: absolute;
  position-anchor: --tooltip-anchor;

  bottom: calc(anchor(top) + 8px); /* 8px above the anchor's top edge */
  left: anchor(center);
  transform: translateX(-50%);

  background: #1e293b;
  color: white;
  padding: 6px 12px;
  border-radius: 6px;
  font-size: 0.8rem;
  white-space: nowrap;
  pointer-events: none;
}

The tooltip can now be inside a <body> direct child for z-index stacking while still being visually attached to the button.

Dropdown menu with position-try flipping

.menu-btn {
  anchor-name: --menu-anchor;
}

.dropdown {
  position: fixed; /* in top-layer context */
  position-anchor: --menu-anchor;

  top: anchor(bottom);
  left: anchor(left);
  width: anchor-size(width); /* match anchor width */

  background: white;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.12);
  padding: 4px;

  /* Flip above if not enough space below */
  position-try-fallbacks: flip-block;
}

Connecting a label to a form input

/* Input is the anchor */
.field-input {
  anchor-name: --field;
}

/* Error message floats below the input */
.field-error {
  position: absolute;
  position-anchor: --field;
  top: calc(anchor(bottom) + 4px);
  left: anchor(left);

  color: #ef4444;
  font-size: 0.75rem;
  font-weight: 500;
  background: #fef2f2;
  padding: 4px 8px;
  border-radius: 4px;
  border: 1px solid #fca5a5;
}

Sizing with anchor-size()

.popover-trigger {
  anchor-name: --pop-anchor;
  width: 200px;
}

.popover-content {
  position: absolute;
  position-anchor: --pop-anchor;
  top: anchor(bottom);
  left: anchor(left);

  /* Match the trigger width */
  width: anchor-size(width);

  /* Or use a multiplier */
  min-width: calc(anchor-size(width) * 1.5);

  background: white;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  padding: 12px;
}

anchor-size(width) and anchor-size(height) return the computed width and height of the anchor element.

Common Mistakes

  • Using anchor-name without the -- prefix (it must be a custom identifier starting with --)
  • Expecting anchor positioning to work without position: absolute or position: fixed on the positioned element
  • Forgetting that position-try-fallbacks requires specific keyword values like flip-block and flip-inline
  • Assuming wide browser support (Anchor Positioning is Chrome 125+ only as of mid-2024)

Note

Anchor Positioning is the CSS replacement for JavaScript libraries like Floating UI and Popper.js. For tooltips, dropdowns, and context menus that need top-layer stacking but visual attachment, this is the native CSS solution.

Exercises

Write CSS to style the HTML scaffold. The preview updates live — when it looks right, mark as done.

Loading editor…

Completed: 0 / 2 exercises

Knowledge Check

Question 1 of 3

What problem does CSS Anchor Positioning solve that was previously handled by JavaScript?