Tooltip

A Tailwind CSS tooltip component for displaying informational text on hover or when the element receives keyboard focus.

<button class="btn" aria-describedby="tip-1">Hover me</button>
<div id="tip-1" class="tooltip" role="tooltip">Tooltip text</div>

To attach a tooltip to a trigger, point the trigger's aria-describedby at the tooltip's id.


Placement

Use data-sp-placement on the tooltip to control its position relative to the trigger (default is top).

<button class="btn" aria-describedby="tip-left">Left</button>
<div id="tip-left" class="tooltip" role="tooltip" data-sp-placement="left">Left tooltip</div>
<button class="btn" aria-describedby="tip-top">Top</button>
<div id="tip-top" class="tooltip" role="tooltip" data-sp-placement="top">Top tooltip</div>
<button class="btn" aria-describedby="tip-bottom">Bottom</button>
<div id="tip-bottom" class="tooltip" role="tooltip" data-sp-placement="bottom">Bottom tooltip</div>
<button class="btn" aria-describedby="tip-right">Right</button>
<div id="tip-right" class="tooltip" role="tooltip" data-sp-placement="right">Right tooltip</div>

Animation

The tooltip includes a default fade and zoom animation. Add no-animation to disable it, or use your own classes with data-[state=open]: selectors.

<button class="btn" aria-describedby="tip-default">Default</button>
<div id="tip-default" class="tooltip" role="tooltip">Default animation</div>
<button class="btn" aria-describedby="tip-noanim">No Animation</button>
<div id="tip-noanim" class="tooltip no-animation" role="tooltip">No animation</div>
<button class="btn" aria-describedby="tip-slide">Slide from Bottom</button>
<div
  id="tip-slide"
  class="tooltip no-animation data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-bottom"
  role="tooltip"
>
  Custom animation
</div>

The default animations use tw-animate-css utilities. You can customize or replace these with your own animations.


How it works

The tooltip component uses a small JavaScript module that handles showing, hiding, and positioning the tooltip content.

Structure

A tooltip consists of two elements linked by aria-describedby:

  1. Any focusable element (button, link, etc.) with aria-describedby="tooltip-id"
  2. .tooltip with a matching id and role="tooltip" — the floating content panel
<button aria-describedby="my-tip">Hover me</button>
<div id="my-tip" class="tooltip" role="tooltip">Tooltip text</div>

The trigger and the tooltip can live anywhere in the DOM as long as the id matches.

Opening and closing

The tooltip opens automatically when the user hovers over or focuses the trigger. It closes when the mouse leaves or the trigger loses focus. Pressing Escape also closes the tooltip.

Tooltips do not move focus into themselves and do not intercept clicks — clicking the trigger does whatever the trigger normally does (submit a form, navigate, etc.).

Animation

The tooltip includes a default fade and zoom animation. When shown, the JavaScript sets data-state="open" on the tooltip element.

To customize animations, add no-animation to disable the defaults and use your own classes with data-[state=open]: selectors:

<div
  id="my-tip"
  class="tooltip no-animation data-[state=open]:animate-in data-[state=open]:slide-in-from-bottom"
  role="tooltip"
>
  <!-- Custom slide animation -->
</div>

Accessibility

The tooltip JavaScript module shows content on both hover and keyboard focus, and pressing Escape closes it.

Add role="tooltip" to the tooltip element so screen readers announce it correctly:

<div id="my-tip" class="tooltip" role="tooltip">Tooltip text</div>

aria-describedby on the trigger is required — that's how the tooltip is discovered. Without it the JavaScript has no way to know which tooltip belongs to which trigger.

<button class="btn" aria-describedby="save-tip">Save</button>
<div id="save-tip" class="tooltip" role="tooltip">
  Saves your changes
</div>

Keyboard navigation

KeyAction
TabFocus trigger to show tooltip
EscapeCloses the tooltip

Class reference

All available classes for the tooltip component.

ClassDescription
tooltipThe floating content that appears on hover/focus
tooltip-arrowArrow element (auto-injected by JavaScript)
no-animationDisables default animation on the tooltip
<button aria-describedby="my-tip">Hover me</button>
<div id="my-tip" class="tooltip" role="tooltip">Tooltip text</div>

Data attributes

All data attributes for the tooltip component.

AttributeElementDescription
aria-describedbyTriggerRequired — id of the linked .tooltip
data-sp-placement.tooltipTooltip position (default: top)
data-state.tooltipSet to open when tooltip is visible
<button class="btn" aria-describedby="my-tip">Hover me</button>
<div id="my-tip" class="tooltip" role="tooltip" data-sp-placement="bottom">
  Tooltip text
</div>