Skip to content

Tooltip

A bubble with an addition to something that is already on the screen. It must never carry information the user needs: on a touch screen there is neither hover nor focus until something is tapped.

If the text is needed to fill in a field, it belongs in a Help Text under the field.

The bubble is hidden until the trigger gets the mouse or focus. Hold the mouse over the button below, or move to it with Tab, and it appears:

Two things must be right:

WhatWhy
aria-describedby from the trigger to the bubbleWithout it the bubble is just something that appears on the screen, and is never announced
role="tooltip" on the bubbleSays what kind of text it is

The bubble is shown on :hover and on :focus-within. The focus part is not optional: a bubble that only appears with the mouse does not exist for someone using the keyboard.

A button with only an icon needs a name, not a help bubble. The two are different things:

<span class="lt-tooltip">
<button class="lt-button" data-variant="ghost" type="button"
aria-label="Archive the case" aria-describedby="archive-hint">
<svg aria-hidden="true" width="20" height="20">…</svg>
</button>
<span class="lt-tooltip__bubble" role="tooltip" id="archive-hint">
The case can be brought back later
</span>
</span>

aria-label is the name the button is announced with. The bubble is the addition. If you use the bubble as the name, the button has no name until it gets focus.

ClassWhat it is
.lt-tooltipThe wrapper around the trigger and the bubble
.lt-tooltip__bubbleThe bubble with the text
VariableDefault
--lt-tooltip-width16rem
--lt-tooltip-paddingvar(--lt-spacing-1) var(--lt-spacing-2)
--lt-tooltip-radiusvar(--lt-spacing-1)

The bubble sits above the trigger. If the trigger is at the very top of the page, you have to move the bubble down yourself:

.lt-tooltip__bubble {
inset-block-end: auto;
inset-block-start: calc(100% + var(--lt-spacing-2));
}
/* The bridge across the gap must move down too, otherwise the bubble disappears on the way to it. */
.lt-tooltip:is(:hover, :focus-within)::before {
inset-block-end: auto;
inset-block-start: 100%;
}

The bubble is display: none when hidden, so it takes no space, and fades in with opacity. A hidden bubble is out of the accessibility tree, but aria-describedby reads the text it points to even when it is hidden, so the description follows the button before the bubble is shown.

See Customising for how the variables and the layer work.

  • Nothing that exists only in the bubble can be necessary. Assume half the users never see it.
  • Keep the text short. The bubble cannot scroll. The mouse can move from the button up onto the bubble without it disappearing, but it closes when the mouse leaves both.
  • Do not put links or buttons inside. The bubble is a description, not a panel.
  • The bubble cannot be dismissed with Escape. WCAG 1.4.13 requires that content appearing on hover and focus can be dismissed without moving the mouse or focus. That requires JavaScript, and Tooltip is only CSS. So use it only where the bubble does not cover anything the user needs to see, or use Popover, which closes with Escape.
  • The bubble is not moved in from the edge of the screen. It sits centred above the button. If the button is right at the left or right edge on a narrow screen, part of the bubble ends up outside. Moving it requires anchor positioning in CSS, which is not in all browsers yet, or JavaScript. So do not put a button with a bubble right at the edge.
  • A bubble on a field that already has help text is doubling up. Choose one.