Components
Tooltip
Built on top of Anchor.
Add the .tooltip class alongside .anchor on the
wrapper. Wire interestfor on the trigger to the
.anchor-floating[popover="hint"] element's ID.
Full support Supported since v144. Full support Supported since v149. Partial support
Missing:
popover-hint.
Basics
Set the tooltip text inside .anchor-floating[popover="hint"].
Save your changes
<span class="anchor tooltip"> <button class="button" interestfor="tooltip-basic" commandfor="tooltip-basic" command="toggle-popover">Save</button> <span class="anchor-floating" id="tooltip-basic" popover="hint">Save your changes</span></span>Alignment
Override --anchor-position-area on the wrapper with any valid
position-area value.
Above
Before
After
Below
<div class="tooltip-alignment-grid"> <span class="anchor tooltip" style="--anchor-position-area: block-start;"> <button class="button" interestfor="tooltip-top" commandfor="tooltip-top" command="toggle-popover">Top</button> <span class="anchor-floating" id="tooltip-top" popover="hint">Above</span> </span> <span class="anchor tooltip" style="--anchor-position-area: inline-start;"> <button class="button" interestfor="tooltip-start" commandfor="tooltip-start" command="toggle-popover">Start</button> <span class="anchor-floating" id="tooltip-start" popover="hint">Before</span> </span> <span class="anchor tooltip" style="--anchor-position-area: inline-end;"> <button class="button" interestfor="tooltip-end" commandfor="tooltip-end" command="toggle-popover">End</button> <span class="anchor-floating" id="tooltip-end" popover="hint">After</span> </span> <span class="anchor tooltip" style="--anchor-position-area: block-end;"> <button class="button" interestfor="tooltip-bottom" commandfor="tooltip-bottom" command="toggle-popover">Bottom</button> <span class="anchor-floating" id="tooltip-bottom" popover="hint">Below</span> </span></div>
<style> .tooltip-alignment-grid { display: grid; gap: var(--size-3); grid-template-areas: ". top . " "start . end" ". bottom . "; justify-items: center; align-items: center; }
.tooltip-alignment-grid> :nth-child(1) { grid-area: top; }
.tooltip-alignment-grid> :nth-child(2) { grid-area: start; }
.tooltip-alignment-grid> :nth-child(3) { grid-area: end; }
.tooltip-alignment-grid> :nth-child(4) { grid-area: bottom; }</style>Arrow
Add the .with-arrow class on the .tooltip wrapper
to render a small arrow pointing from the tooltip toward the trigger.
Save your changes
<span class="anchor tooltip with-arrow"> <button class="button" interestfor="tooltip-arrow" commandfor="tooltip-arrow" command="toggle-popover">Save</button> <span class="anchor-floating" id="tooltip-arrow" popover="hint">Save your changes</span></span>Rich content
Place any inline markup inside .anchor-floating[popover="hint"].
Press ⌘ + K to open the command palette.
<span class="anchor tooltip"> <button class="button" interestfor="tooltip-rich" commandfor="tooltip-rich" command="toggle-popover">Keyboard shortcuts</button> <span class="anchor-floating" id="tooltip-rich" popover="hint"> Press <kbd>⌘</kbd> + <kbd>K</kbd> to open the command palette. </span></span>API
| Type | Modifiers | Default | Description |
|---|---|---|---|
| Container | .anchor.tooltip | - | Wrapper element. Combines the anchor primitive with the tooltip styling. |
| Floating | .anchor-floating[popover="hint"] | - | Floating tooltip surface. Uses the hint
popover so it auto-shows on interestfor hover/focus. |
| Trigger | interestfor="id" | - | Add to the trigger element pointing to the floating element's ID. Pair
with commandfor and command="toggle-popover" for
touch support. |
| Arrow | .with-arrow | - | Add to the .tooltip wrapper to render an arrow pointing from
the tooltip toward the trigger. |
| Position | --anchor-position-area | block-start | CSS custom property. Any valid position-area value. |
Browser support
Full support Supported since v144. Full support Supported since v149. Partial support
Missing:
popover-hint.
See also the full browser support guide.
Installation
@layer components.extended { :where(.tooltip) { --_tooltip-bg: light-dark(var(--gray-13), var(--gray-3)); --_tooltip-color: light-dark(var(--gray-1), var(--gray-15)); --_tooltip-offset: var(--size-2);
&>.anchor-floating { background-color: var(--_tooltip-bg); border-radius: var(--radius-2); color: var(--_tooltip-color); font-size: var(--font-size-05); line-height: 1.3; margin: var(--_tooltip-offset); max-inline-size: 240px; /* UA sets overflow: auto on [popover], which clips the arrow. */ overflow: visible; padding-block: var(--size-1); padding-inline: var(--size-2); position-area: var(--anchor-position-area, block-start); position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline; position-visibility: anchors-visible; text-align: center; text-wrap: pretty; }
/* Optional arrow pointing from the tooltip toward the trigger. Anchored to the same --anchor so it flips together with the tooltip when position-try-fallbacks kicks in. */ &.with-arrow { --_arrow-size: var(--size-2);
&>.anchor-floating { /* Reserve space so the arrow doesn't overlap the trigger. */ --_tooltip-offset: calc(var(--size-2) + var(--_arrow-size) / 2); }
&>.anchor-floating::before { background-color: var(--_tooltip-bg); block-size: var(--_arrow-size); content: ""; inline-size: var(--_arrow-size); inset-block-end: calc(var(--_arrow-size) / -2); inset-inline-start: 50%; position: absolute; rotate: 45deg; translate: -50% 0; } }
/* Fade */ &>.anchor-floating[popover] { opacity: 0; transition: display 0.15s allow-discrete, opacity 0.15s var(--ease-out-1), overlay 0.15s allow-discrete;
&:popover-open { opacity: 1;
@starting-style { opacity: 0; } } } }}@layer components.root { :where(.anchor) { anchor-name: --anchor; anchor-scope: --anchor; display: inline-block; inline-size: fit-content;
/* Always-visible */ &>.anchor-floating:not([popover]) { block-size: max-content; inline-size: max-content; position: absolute; position-anchor: --anchor; position-area: var(--anchor-position-area, start end); translate: var(--_anchor-tx, 0) var(--_anchor-ty, 0); }
/* Hover-triggered */ &>.anchor-floating[popover] { inset: unset; margin: 0; position: absolute; position-area: var(--anchor-position-area, start end); translate: var(--_anchor-tx, 0) var(--_anchor-ty, 0); } }}