CSS Anchor Positioning

CSS anchor positioning places an absolutely or fixed-positioned element relative to another element called an anchor. It is useful for tooltips, menus, labels, callouts, and other interface elements that must follow a specific control.

Traditional absolute positioning normally uses the containing block as its reference. Anchor positioning lets the positioned element use the location and size of a different element instead.

How Anchor Positioning Works

A basic anchor-positioned layout has two parts:

  1. An anchor element declares a dashed identifier with anchor-name.
  2. An absolutely or fixed-positioned element selects that anchor with position-anchor.

The positioned element can then use position-area, anchor(), or anchor-size() to refer to the anchor.

Example

/* Give the button a reusable anchor name */
.help-button {
  anchor-name: --help-button;
}

/* Position the panel relative to that anchor */
.help-panel {
  position: absolute;
  position-anchor: --help-button;
  position-area: block-end span-inline-end;
}

CSS anchor names are dashed identifiers, so they must begin with two hyphens.

Place an Element with position-area

The position-area property divides the area around an anchor into a conceptual grid. It provides a concise way to place content above, below, beside, or across part of the anchor.

Value General placement
top Above the anchor
bottom Below the anchor
left To the left of the anchor
right To the right of the anchor
block-start Before the anchor in the block direction
block-end After the anchor in the block direction
inline-start Before the anchor in the inline direction
inline-end After the anchor in the inline direction

Logical directions such as block-end and inline-start adapt to writing mode and text direction. They are generally more flexible than physical directions.

Example

/* Place the tooltip above and center it on the anchor */
.tooltip {
  position: fixed;
  position-anchor: --account-button;
  position-area: block-start center;
  margin-block-end: 0.5rem;
}

Use the anchor() Function

The anchor() function obtains the position of an anchor edge. It can be used in inset properties such as top, right, bottom, left, and their logical equivalents.

Syntax

/* Use the default anchor selected by position-anchor */
top: anchor(bottom);

/* Refer directly to a named anchor */
left: anchor(--menu-button left);

/* Supply a fallback length if the anchor cannot resolve */
top: anchor(--menu-button bottom, 4rem);

Example

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

.menu {
  position: absolute;
  position-anchor: --menu-button;

  /* Start below and align with the anchor's left edge */
  top: calc(anchor(bottom) + 0.5rem);
  left: anchor(left);
}

An omitted name refers to the element's default anchor. Naming the anchor inside anchor() is useful when different inset calculations need different anchors.

Match the Anchor's Size

The anchor-size() function obtains a dimension of an anchor. It can make a menu at least as wide as its button or size another positioned element relative to its anchor.

Example

.dropdown {
  position: absolute;
  position-anchor: --dropdown-button;
  position-area: block-end span-inline-end;

  /* Keep the menu at least as wide as its anchor */
  min-width: anchor-size(width);
  max-width: min(24rem, calc(100vw - 2rem));
}

The supported size keywords include width, height, block, inline, self-block, and self-inline.

Add Fallback Positions

An anchored element may overflow when its preferred side has insufficient space. The position-try-fallbacks property provides alternative positions for the browser to try.

Example

.tooltip {
  position: fixed;
  position-anchor: --target;
  position-area: block-start;

  /* Try the opposite block side if the preferred side overflows */
  position-try-fallbacks: flip-block;
}

Common try tactics include flip-block, flip-inline, and flip-start. Multiple tactics or position-area values can be listed in priority order.

Example

.menu {
  position: fixed;
  position-anchor: --actions;
  position-area: block-end span-inline-end;

  /* Try several alternatives in sequence */
  position-try-fallbacks:
    flip-block,
    flip-inline,
    flip-block flip-inline;
}

Define a Custom Position Attempt

The @position-try rule defines a named fallback containing accepted positioning and sizing declarations.

Example

/* Define a custom alternative above the anchor */
@position-try --above-wide {
  position-area: block-start span-inline-end;
  max-width: 22rem;
}

.notice {
  position: fixed;
  position-anchor: --notice-button;
  position-area: block-end span-inline-end;

  /* Try a tactic and then the custom option */
  position-try-fallbacks: flip-inline, --above-wide;
}

The position-try-order property can prioritize an option according to available width, height, inline size, or block size rather than using only list order.

Control Anchor Visibility

The position-visibility property can hide a positioned element when its anchor becomes invalid or invisible, or when the positioned element still overflows after fallback attempts.

Example

.anchored-label {
  position: fixed;
  position-anchor: --field;

  /* Hide when the anchor is fully clipped from view */
  position-visibility: anchors-visible;
}

The current specification defines conditions including anchors-valid, anchors-visible, and no-overflow.

Limit Reused Anchor Names

Anchor names do not have to be globally unique. However, a repeated component may need anchor-scope so each positioned element resolves the anchor within its own component.

Example

.product {
  /* Keep this anchor name local to each product component */
  anchor-scope: --product-action;
}

.product__button {
  anchor-name: --product-action;
}

.product__menu {
  position: absolute;
  position-anchor: --product-action;
  position-area: block-end;
}

Complete Anchor Positioning Example

This complete page opens a popover next to its button. Anchor positioning places it below the button and attempts the opposite side when space is limited. The ordinary inset declarations provide a basic fallback.

Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS Anchor Positioning Example</title>
  <style>
    /* Place the demonstration near the center */
    body {
      min-height: 100vh;
      margin: 0;
      display: grid;
      place-items: center;
      font-family: Arial, sans-serif;
    }

    #actions-button {
      anchor-name: --actions-button;
      padding: 0.7rem 1rem;
    }

    #actions-menu {
      /* Basic fallback for browsers without anchor positioning */
      position: fixed;
      inset: 1rem auto auto 1rem;

      border: 0;
      border-radius: 0.75rem;
      padding: 0.5rem;
      box-shadow: 0 0.5rem 2rem rgb(0 0 0 / 22%);
    }

    @supports (position-area: block-end) {
      #actions-menu {
        /* Position the menu relative to the button */
        position-anchor: --actions-button;
        position-area: block-end span-inline-end;
        position-try-fallbacks: flip-block, flip-inline;
        inset: auto;
        margin-block: 0.5rem;
        min-width: anchor-size(width);
      }
    }

    #actions-menu button {
      display: block;
      width: 100%;
      padding: 0.6rem 1rem;
      border: 0;
      background: transparent;
      text-align: start;
    }
  </style>
</head>
<body>
  <button id="actions-button" type="button" popovertarget="actions-menu">
    Actions
  </button>

  <div id="actions-menu" popover>
    <button type="button">Edit</button>
    <button type="button">Duplicate</button>
    <button type="button">Archive</button>
  </div>
</body>
</html>

Tip: CSS Anchor Positioning Level 1 remains a working draft. Check target-browser support, use feature queries, and provide a usable fallback for important controls.

Best Practices

  • Use logical directions when the interface may support different writing modes.
  • Prefer position-area for common placements and anchor() for precise edge calculations.
  • Add fallback positions for content near viewport edges.
  • Constrain wide or tall anchored content so it remains usable on small screens.
  • Use anchor-scope when reusable components repeat anchor names.
  • Remember that positioning does not provide interaction or accessibility semantics.

Conclusion

CSS anchor positioning connects positioned content to a meaningful element instead of only its containing block. Use named anchors, position-area, anchor functions, size references, and fallback attempts to build adaptable tooltips, menus, and callouts while retaining a practical fallback for browsers that do not support the feature.



Found This Page Useful? Share It!
Get the Latest Tutorials and Updates
Join us on Telegram