Tooltip
A CSS-only tooltip anchored with anchor-name and position-anchor. The tooltip is revealed on hover or focus, with a classic absolute-positioning fallback for unsupported browsers.
0 KB JavaScript
~30 CSS lines
anchor positioned tooltip
hover/focus reveal
Preview
The word CSSCascading Style Sheets, created by Håkon Wium Lie in 1994. has evolved a lot. Today, you can do complex layoutSubgrid, container queries, anchor positioning… without a line of JavaScriptThe scripting language of the web, created in 10 days in 1995..
The code
The markup
<span class="anchor anchor-1" tabindex="0" aria-describedby="tooltip-1">
Anchor
<span id="tooltip-1" class="tooltip tooltip-1" role="tooltip">Tooltip text.</span>
</span>CSS mechanisms
/* ----------------------------------------------------------------------------
* Anchor
* ---------------------------------------------------------------------------- */
/**
* Tooltipped term: dashed underline + accent color signals it's
* interactive. `position: relative` is the fallback positioning
* context for the tooltip.
*/
.anchor {
cursor: help;
position: relative;
/* add your styles here */
}
/**
* Anchor name registrations: each term gets a unique `--aN` so
* its tooltip can target it explicitly via `position-anchor`.
*/
.anchor-1 {
anchor-name: --a1;
}
/* ----------------------------------------------------------------------------
* Tooltip Box
* ---------------------------------------------------------------------------- */
/**
* Tooltip bubble. Hidden by default (opacity 0, pointer-events none).
* Includes a classic absolute-positioning fallback at the bottom so
* unsupported browsers still get a centered tooltip above the term.
*/
.tooltip {
position: absolute;
opacity: 0;
pointer-events: none;
z-index: 10;
/* add your styles here */
/**
* Classic positioning fallback (used when anchor-positioning
* is not supported): center horizontally above the parent.
*/
bottom: calc(100% + 8px);
left: 50%;
translate: -50% 0;
}
/* ----------------------------------------------------------------------------
* Anchor Positioning Override
* ---------------------------------------------------------------------------- */
/**
* When the browser supports `anchor-name`, override the fallback
* positioning with proper anchor-based coordinates: each tooltip
* sits above the top edge of its anchor and is horizontally
* centered on the anchor's center.
*/
@supports (anchor-name: --a) {
.tooltip-1 {
position-anchor: --a1;
bottom: anchor(top);
left: anchor(center);
margin-bottom: 8px;
translate: -50% 0;
}
}
/**
* Reveal the tooltip on hover, focus, or focus-within (keyboard
* users). Animates opacity and removes the slight Y translate.
*/
.anchor:hover .tooltip,
.anchor:focus .tooltip,
.anchor:focus-within .tooltip {
opacity: 1;
transform: translateY(0);
}Benefits
-
01.
No JavaScript state
The tooltip is revealed with CSS using
:hover,:focus, and:focus-within. No event listeners, no runtime state, no hydration. -
02.
Keyboard reachable
The anchor can receive focus with
tabindex="0", so keyboard users can reveal the tooltip without relying on hover. -
03.
Precise positioning
anchor-nameandposition-anchorlet the tooltip position itself from the anchor’s real coordinates instead of depending only on parent-relative offsets. -
04.
Progressive fallback
Unsupported browsers still get a classic absolute-positioning fallback. The tooltip remains usable, even without CSS Anchor Positioning.
Current limitations
-
01.
Anchor declarations
Each tooltip needs a unique anchor name, such as
--a1, and a matchingposition-anchor. This makes the association explicit but adds per-tooltip CSS. -
02.
Browser support
CSS Anchor Positioning is still progressive enhancement. Use
@supportsand keep a fallback for browsers that do not supportanchor-nameyet. -
03.
Accessibility limits
Use
aria-describedbyandrole="tooltip"when appropriate, but keep tooltip content short. Complex interactive content should use another pattern.