tooltip-wc
Progressive enhancement tooltips: native title fallback upgraded to styled popovers with arrows and positioning.
Overview
Tooltips use a title-first progressive enhancement approach. The title attribute provides a no-JS fallback (native browser tooltip). When JavaScript loads, the init script reads the title, removes it, and creates a styled popover with arrows and positioning.
Progressive Enhancement
| State | What the user sees |
|---|---|
| No JavaScript | Native browser tooltip from title attribute |
| JavaScript loaded | Styled popover with arrow, positioned via CSS Anchor or JS fallback |
Simple Text Tooltip (Tier 1)
Add title and data-tooltip (no value) to any element. The init script creates the popover automatically.
Positions
Use data-tooltip-position to control where the tooltip appears relative to the trigger.
With Different Elements
Tooltips work on any focusable element: buttons, links, and elements with tabindex.
Attributes
| Attribute | On | Description |
|---|---|---|
title |
trigger | Tooltip text. Read by init script and removed to prevent native double-tooltip. |
data-tooltip |
trigger | Marker for init script discovery. No value = create from title. With value = reference popover by ID. |
data-tooltip-position |
trigger | Position: top (default), bottom, left, or right. |
Rich HTML Tooltip (Tier 2)
For tooltips with formatted content (keyboard shortcuts, icons, multiple lines), use data-tooltip="id" to reference an existing popover element. The title provides a plain-text no-JS fallback.
Card Variant (Tier 3)
For richer content previews like user profiles or link previews, use <tooltip-wc data-variant="card">. Cards use popover="manual" for interactive content and have longer show/hide delays.
Differences from Regular Tooltip
| Feature | Tooltip (Tier 1/2) | Card variant |
|---|---|---|
| Content model | title or data-tooltip="id" |
[data-trigger] + [data-content] |
| Appearance | Dark, compact, with arrow | Light card surface, border, shadow, no arrow |
| Show delay | 200ms | 300ms |
| Hide delay | 100ms | 200ms |
| Popover type | hint |
manual (supports interactive content) |
| ARIA | role="tooltip", aria-describedby |
None (supplementary content) |
tooltip-wc with Title Fallback
The <tooltip-wc> component also reads title from its trigger as a content source (lowest priority after <template data-tooltip> and data-content). This gives progressive enhancement to the web component path too.
Ctrl + S
Content priority in tooltip-wc:
<template data-tooltip>(rich HTML)data-contentattribute (plain text, backward compatible)titleon trigger (PE baseline — read and removed)
Pure HTML Tooltips — interestfor (Tier 0)
For simple tooltips that don't need arrows, custom positioning, or rich content, you can skip the init script entirely. The interestfor attribute (native in Chrome 133+, polyfilled in other browsers) handles hover/focus timing and popover show/hide declaratively.
Custom Timing
Control show/hide delays with CSS custom properties:
When to Use Which
| Use case | Approach |
|---|---|
| Simple text hint on a button/link | title + data-tooltip (Tier 1) |
| Rich content (kbd shortcuts, icons) | data-tooltip="id" referencing a popover (Tier 2) |
| Interactive hover card (profiles, previews) | <tooltip-wc data-variant="card"> (Tier 3) |
| Zero-JS inline definition | interestfor + popover="hint" (Tier 0) |
How It Works
Popover API
Tooltips use the native Popover API with popover="hint". This renders tooltips in the browser's top layer, avoiding z-index conflicts and overflow clipping issues.
CSS Anchor Positioning
In modern browsers (Chrome 125+, Safari 18+), tooltips use CSS Anchor Positioning for smooth, hardware-accelerated positioning. Older browsers fall back to JavaScript positioning automatically.
Browser Support
| Browser | Positioning | Notes |
|---|---|---|
| Chrome 125+ | CSS Anchor | Full support |
| Safari 18+ | CSS Anchor | Full support |
| Firefox | JS Fallback | Anchor positioning not yet supported |
| Older browsers | JS Fallback | Requires Popover API support |
Show Delay (tooltip-wc)
When using <tooltip-wc>, control how long to wait before showing with data-tooltip-delay. Default is 200ms.
Events & API (tooltip-wc)
Events
| Event | Description |
|---|---|
tooltip-show |
Fired when the tooltip becomes visible. |
tooltip-hide |
Fired when the tooltip is hidden. |
JavaScript API
| Method/Property | Type | Description |
|---|---|---|
show() |
method | Show the tooltip immediately. |
hide() |
method | Hide the tooltip immediately. |
isVisible |
property | Read-only boolean indicating if the tooltip is currently visible. |
Keyboard Support
Tooltips appear on keyboard focus and can be dismissed with the Escape key. Escape handling is built into the Popover API.
| Key | Action |
|---|---|
| Tab | Focus the trigger element, showing the tooltip |
| Escape | Hide the tooltip while keeping focus on the trigger |
Use Tab to focus the button below, then press Escape to hide the tooltip:
Accessibility
ARIA Attributes
- The tooltip has
role="tooltip"andpopover="hint" - The trigger gets
aria-describedbypointing to the tooltip (set by init script) - The tooltip arrow has
aria-hidden="true" - Uses the browser's top layer for proper stacking without z-index conflicts
Screen Reader Behavior
When the trigger receives focus, screen readers announce the element followed by the tooltip content (via aria-describedby). This provides context without requiring visual interaction.
Best Practices
- Keep tooltip content brief and informative
- Don't put essential information only in tooltips
- Ensure the trigger element is focusable
- Use tooltips for supplementary information, not primary content
- Avoid interactive content inside tooltips (use cards instead)