Tooltips

Tooltips

Material Design 3 tooltips, from the HTML.

A child .tooltip is the bubble. No tooltipped class is required. They are CSS only on hover and keyboard focus. Helpers are only for placement and the rich variant: top (the default), bottom, left, right, rich / max.

Tokens follow the M3 tooltip spec. A plain tooltip is inverse-surface / inverse-on-surface, 4dp corners, body-small, 24dp minimum, 4/8dp padding, 200dp max, no elevation and no caret. It sits 4dp from the activator. M3 prefers above.

Inside a <button> the bubble has to be a <span> — a <div> is not phrasing content and the parser will hoist it. Icon-only buttons still need .circle so the span is not treated as a label.

<button type="button" class="circle" aria-label="Add" aria-describedby="tip-add-to-album">
  <span class="material-symbols" aria-hidden="true">add</span>
  <span class="tooltip" id="tip-add-to-album">Add to album</span>
</button>

<button type="button" class="circle" aria-label="Below" aria-describedby="tip-below">
  <span class="material-symbols" aria-hidden="true">arrow_downward</span>
  <span class="tooltip bottom" id="tip-below">Below</span>
</button>

Rich

rich (or BeerCSS’s max) is the rich tooltip: surface, elevation 2, 12dp corners, 320dp max. A heading is the title (title-small), a <p> is supporting text (body-medium), and a trailing <nav> is the action. Rich bubbles can receive pointer events so the action is usable.

Saved offline

This stop is stored on the device so it still opens without a signal.

<div>
  <button type="button" class="tonal">Why this is saved</button>
  <div class="tooltip rich bottom">
    <h3>Saved offline</h3>
    <p>This stop is stored on the device so it still opens without a signal.</p>
    <nav>
      <button type="button" class="text">Got it</button>
    </nav>
  </div>
</div>

A rich tooltip with an action cannot live inside a <button> — that would nest buttons. Put the bubble next to the control, wrapped in a parent.

JavaScript

The CSS path does not need AutoInit. The JS plugin is still there for data-tooltip, delayed show/hide, and keeping the bubble inside the viewport. Add tooltipped to the activator. data-tooltip is the text; data-position is top, right, bottom, or left. AutoInit() starts every .tooltipped except those marked no-autoinit. The generated element gets both .tooltip and .material-tooltip.

Bottom Top Left Right

<a class="tooltipped" data-position="bottom" data-tooltip="I am a tooltip" href="#!">
  Hover me
</a>

For HTML, point data-tooltip-id at an element. That element is moved into the tooltip and the bubble is marked rich. Leave data-tooltip off so the HTML is kept. There is no data-html attribute and no unsafeHTML option.

With HTML

<a class="tooltipped" href="#!"
   data-position="bottom" data-tooltip-id="tooltip-content">
  With HTML
</a>
<div id="tooltip-content" hidden>
  <h3>Chart</h3>
  <p>This is a tooltip with a <a href="https://github.com">link</a>.</p>
</div>

Initialization

The IIFE bundle exposes Expressive.Tooltip. Call init yourself when you need options other than the defaults, or let Expressive.AutoInit() start every .tooltipped.

document.addEventListener('DOMContentLoaded', function() {
  const elems = document.querySelectorAll('.tooltipped');
  const instances = Expressive.Tooltip.init(elems, {
    enterDelay: 200
  });
});

Per-instance options can also be passed through AutoInit:

Expressive.AutoInit(document.body, {
  Tooltip: { enterDelay: 200 }
});

Options

Constructor and init options. data-tooltip, data-position, and data-tooltip-id are read from the element and override these defaults. Attributes are read again each time the tooltip opens, so changing them later takes effect on the next show.

Name Type Default Description
exitDelay Number 200 Delay before the tooltip disappears, in milliseconds.
enterDelay Number 0 Delay before the tooltip appears, in milliseconds.
tooltipId String Id of an element used as the tooltip body. Set by data-tooltip-id. Marks the bubble rich.
text String '' Plain-text content. Set by data-tooltip. Ignored when tooltipId is set.
margin Number 4 Distance from the activator, in pixels, not counting transitionMovement. M3 is 4dp.
inDuration Number 250 Enter transition duration, in milliseconds.
opacity Number 1 Opacity of the tooltip when shown.
outDuration Number 200 Exit transition duration, in milliseconds.
position String 'bottom' Direction: 'top', 'right', 'bottom', or 'left'. Set by data-position. The CSS-only default is above.
transitionMovement Number 10 How far the tooltip moves during its transition, in pixels.

Methods

All methods are called on the plugin instance. You can get the instance like this:
const instance = Expressive.Tooltip.getInstance(elem);

Hover me

.open();

Show the tooltip.

instance.open();
.close();

Hide the tooltip.

instance.close();
.destroy();

Destroy the plugin instance, remove the tooltip element, and tear down its event handlers.

instance.destroy();

Properties

Name Type Description
el Element The DOM element the plugin was initialized with.
options Object The options the instance was initialized with.
isOpen Boolean Whether the tooltip is open.
isHovered Boolean Whether the activator is hovered.
isFocused Boolean Whether the activator is focused via the keyboard.
tooltipEl Element The generated tooltip element.
  • Source color

    The seed every generated ramp derives from. Pick one and browse the docs — the whole theme follows. Error does not: it is a fixed hue.