CSS Anchor Positioning position-visibility Guide

The CSS Anchor Positioning API introduces the position-visibility property to manage how anchored elements behave when their trigger elements scroll out of view. This property prevents UI components like tooltips, popovers, and floating menus from becoming awkwardly orphaned on screen when their associated anchors are no longer visible. By using position-visibility, developers can control whether an anchored element stays visible, hides automatically, or disappears when constrained by its container, eliminating the need for complex JavaScript scroll and intersection listeners.

The Problem: Floating Orphaned Elements

When pairing an element (such as a tooltip) to an anchor (such as a button inside a scrollable area), normal absolute or fixed positioning can cause visual bugs. As the user scrolls, the button might slide off the top of the viewport, but the tooltip may remain visible, floating in empty space detached from its context.

The position-visibility property solves this by linking the visual rendering of the anchored element directly to the visibility and position of its anchor.

Key Values of position-visibility

The position-visibility property accepts three primary values that dictate how the anchored element responds to scrolling:

  • anchors-visible: This is the most common solution for handling scrolled anchors. The anchored element remains visible only as long as its anchor is visible within its scroll container or viewport. If the anchor is completely clipped or scrolled out of view, the anchored element is automatically hidden.
  • always: The anchored element remains visible at all times, even if the anchor has scrolled completely out of view. In this case, the element will stay fixed at the edge or pinned to where the anchor would be, regardless of whether the user can actually see the anchor.
  • no-overflow: The anchored element is hidden if it overflows the boundaries of its containing block or the viewport. This is useful when an anchor is still partially on screen, but there is no longer enough room to render the anchored element without clipping or visual overlap.

Implementation Example

To apply this behavior, assign the property to the anchored element using CSS:

/* Define the anchor */
.action-button {
  anchor-name: --tooltip-anchor;
}

/* Define the anchored element */
.tooltip {
  position: fixed;
  position-anchor: --tooltip-anchor;
  position-visibility: anchors-visible;
  bottom: anchor(top);
  left: anchor(center);
}

In this implementation, the .tooltip element tracks .action-button. As long as .action-button remains in the visible scroll area, .tooltip is displayed. The moment .action-button scrolls outside the visible boundary, the browser automatically suppresses rendering of .tooltip.

Practical Benefits

  • Zero JavaScript Overhead: Eliminates the need for IntersectionObserver logic or scroll event listeners previously required to toggle visibility classes.
  • Cleaner User Interfaces: Ensures contextual UI elements only appear when their associated context is genuinely present and relevant to the user.
  • Performance: Browser-level visibility calculations occur on the compositor thread, ensuring smooth scrolling without layout thrashing.