Tooltip
Wrap a trigger in .re-tooltip and add a .re-tooltip__bubble sibling with
role="tooltip". Point the trigger’s aria-describedby at the bubble’s id
so assistive technology announces the text — the reference resolves even
while the bubble is visually hidden. The bubble appears on hover and on
keyboard focus (:focus-within); no JavaScript involved. A small arrow
points at the trigger.
The bubble stays hoverable and the gap to the trigger is bridged, so moving the pointer onto the tooltip doesn’t dismiss it — WCAG 1.4.13 Hoverable and Persistent. The CSS-only tooltip does not implement 1.4.13 Dismissable (there’s no Escape-to-hide without moving focus); add a small JS handler if you need that. On touch devices, where there is no hover, the tooltip shows while the trigger has focus — don’t put essential information only in a tooltip.
Placements
Section titled “Placements”Set data-placement="bottom", "start", or "end" on the wrapper; the
default is top. Start/end follow the writing direction.
<div
style="
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--re-space-4);
padding: var(--re-space-12) var(--re-space-16);
"
>
<span class="re-tooltip">
<button class="re-button" type="button" aria-describedby="tip-top">Top</button>
<span class="re-tooltip__bubble" role="tooltip" id="tip-top">Shown above</span>
</span>
<span class="re-tooltip" data-placement="bottom">
<button class="re-button" type="button" aria-describedby="tip-bottom">Bottom</button>
<span class="re-tooltip__bubble" role="tooltip" id="tip-bottom">Shown below</span>
</span>
<span class="re-tooltip" data-placement="start">
<button class="re-button" type="button" aria-describedby="tip-start">Start</button>
<span class="re-tooltip__bubble" role="tooltip" id="tip-start">Shown before</span>
</span>
<span class="re-tooltip" data-placement="end">
<button class="re-button" type="button" aria-describedby="tip-end">End</button>
<span class="re-tooltip__bubble" role="tooltip" id="tip-end">Shown after</span>
</span>
</div> Forced open
Section titled “Forced open”Add data-open to the wrapper to keep the bubble visible — useful for
debugging, documentation, and visual tests.
<div
style="
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--re-space-6);
padding: var(--re-space-12) var(--re-space-16);
"
>
<span class="re-tooltip" data-open>
<button class="re-button" type="button" aria-describedby="tip-open-top">Top</button>
<span class="re-tooltip__bubble" role="tooltip" id="tip-open-top">Shown above</span>
</span>
<span class="re-tooltip" data-placement="bottom" data-open>
<button class="re-button" type="button" aria-describedby="tip-open-bottom">Bottom</button>
<span class="re-tooltip__bubble" role="tooltip" id="tip-open-bottom">Shown below</span>
</span>
<span class="re-tooltip" data-placement="end" data-open>
<button class="re-button" type="button" aria-describedby="tip-open-end">End</button>
<span class="re-tooltip__bubble" role="tooltip" id="tip-open-end">Shown after</span>
</span>
</div> Accessibility
Section titled “Accessibility”- Keyboard — the tooltip has no keyboard model of its own; it’s CSS-only.
Tab to the trigger (a native control such as a
<button>) and the bubble appears via:focus-within; it also appears on:hover. There is no Escape-to-dismiss (see 1.4.13 caveat above) — add a JS handler if you need one. - Focus — only the trigger is focusable, so it keeps its own visible
:focus-visiblering; the bubble is never a focus target. The bubble is hidden withvisibility: hidden/opacity: 0(notdisplay: none) so itsidstays referenceable while invisible. - Semantics — the bubble is a real element with
role="tooltip", and the trigger’saria-describedbypoints at the bubble’sid. Assistive technology announces the bubble text as the trigger’s description even while the bubble is visually hidden. Don’t put essential information only in a tooltip — on touch devices, where there is no hover, it shows only while the trigger has focus. - Notes — fade in/out is shortened to an instant transition under
prefers-reduced-motion: reduce. The bubble derives its colors from the text/bg role tokens, inverting in dark mode and subtree themes without tooltip-specific tokens. See the accessibility guide for the broader WCAG 1.4.13 stance.