CSS Anchor Positioning: Tooltips and Dropdowns Without JS

CSS Anchor Positioning lets you position any element relative to another element — its “anchor” — regardless of their location in the DOM. This eliminates the JavaScript needed for tooltips, dropdown menus, and popovers that must stay visually attached to a trigger element.

Problem: CSS tooltips and dropdown menus require JavaScript to position them relative to their trigger element — calculating offsets, handling viewport overflow, and updating position on scroll is complex boilerplate.

Solution: Use the CSS Anchor Positioning API — assign an anchor-name to the trigger element and reference it with position-anchor on the positioned element. Use anchor() and inset-area to declare the relative position declaratively, with position-try-fallbacks for automatic viewport overflow handling.

The examples below attach a tooltip to a button using anchor-name and position-anchor, position a dropdown relative to its trigger, and use position-try-fallbacks to automatically flip the tooltip when it would overflow the viewport.

/* 1. Mark the trigger element as an anchor */
.tooltip-trigger {
    anchor-name: --my-tooltip;   /* must start with -- like a custom property */
    position: relative;          /* not required, but good practice */
}

/* 2. Position the tooltip relative to its anchor */
.tooltip {
    position: absolute;          /* must be absolutely positioned */
    position-anchor: --my-tooltip;

    /* anchor() references edges of the anchor element:
       anchor(top | right | bottom | left | center | start | end | %) */
    bottom: calc(anchor(top) + 8px);  /* 8px above the anchor's top edge */
    left: anchor(center);             /* horizontally centred on the anchor */
    translate: -50% 0;               /* fine-tune horizontal centring */

    /* Prevent overflow: flip to below the anchor if no space above */
    position-try-fallbacks: flip-block;
}

/* 3. Show only when the trigger is hovered or focused */
.tooltip {
    opacity: 0;
    transition: opacity 0.2s;
}
.tooltip-trigger:hover + .tooltip,
.tooltip-trigger:focus-visible + .tooltip {
    opacity: 1;
}

Anchor positioning for a dropdown menu relative to its button:

/* Dropdown trigger */
.nav-item > button {
    anchor-name: --nav-dropdown;
}

/* Dropdown panel — aligned to the left edge of the button, below it */
.dropdown-panel {
    position: fixed;           /* fixed allows positioning across stacking contexts */
    position-anchor: --nav-dropdown;

    top: anchor(bottom);       /* top of panel = bottom of button */
    left: anchor(left);        /* align left edges */
    min-width: anchor-size(width); /* at least as wide as the button */

    /* Try right-align if overflowing right edge */
    position-try-fallbacks: --dropdown-right-align;
}

@position-try --dropdown-right-align {
    left: unset;
    right: anchor(right);
}

/* Open/close via popover attribute (no JS needed for basic show/hide) */
/*              */
/*  */
.dropdown-panel:popover-open {
    display: block;
}

NOTE: CSS Anchor Positioning is supported in Chrome 125+ and Safari 18.2+. Use the @supports (anchor-name: --test) at-rule to provide a JavaScript fallback for Firefox, which has the feature behind a flag as of late 2024.

Leave Comment

Your email address will not be published. Required fields are marked *