Tooltip

Contextual information on hover/focus.

Top trigger
Bottom trigger
Left trigger
Right trigger

Usage

Just copy-paste the HTML or Figma code into your project.

Floating UI

The tooltip above is positioned with CSS — it is absolutely placed relative to its wrapper and shown on group-hover. This works fine when the trigger is well inside the viewport. Near the edges, however, the tooltip can overflow the window or get clipped by a parent with overflow: hidden / overflow: auto.

To keep the tooltip always visible and inside the window, add floating-ui (a small, dependency-free library) to your page. It repositions the tooltip automatically: it flips it to the opposite side when there is no room, and slides it along the axis so it never causes horizontal or vertical overflow.

See the getting started guide for a full introduction.

When to use

  • Triggers near the edges of the screen where CSS positioning would overflow.
  • Parents with overflow: hidden / auto that clip the tooltip.
  • Any time you want an auto-correcting, bullet-proof tooltip.

1. Add the library

Include floating-ui in your page (via a CDN or your bundler):

<script src="https://cdn.jsdelivr.net/npm/@floating-ui/dom@latest/dist/floating-ui.dom.umd.min.js"></script>

Or install it with npm and import it in your JS:

npm install @floating-ui/dom

2. Mark the trigger and the tooltip

The trigger carries a data-tooltip-trigger attribute whose value matches the tooltip's id. Add a data-placement attribute on the trigger to tell the script which side to prefer (top, bottom, left, right):

<div class="relative group flex">
    <span data-tooltip-trigger="tooltip-a92dc57e" data-placement="top">
      Top trigger
    </span>

    <div class="absolute ..." id="tooltip-a92dc57e" role="tooltip">
      <span class="js_tooltip-text">
        It's a simple tooltip with useful information.
      </span>
    </div>
  </div>

Keep the existing CSS classes and style attribute — they still define the look. The script only overrides the position, top and left at runtime.

3. Add the JavaScript

Copy this snippet — it does the whole job:

// Using the UMD build from the CDN. With npm it's:
//   import { computePosition, autoUpdate, flip, shift } from "@floating-ui/dom";
const { computePosition, autoUpdate, flip, shift } = window.FloatingUIDOM;

// Show/hide is still handled by the existing CSS group-hover rule.
// This script only corrects the position so the tooltip stays in view.

document.querySelectorAll("[data-tooltip-trigger]").forEach((trigger) => {
  const tooltip = document.getElementById(trigger.dataset.tooltipTrigger);
  if (!tooltip) return;

  // Preferred side from data-placement on the trigger (defaults to "bottom").
  const placement = trigger.dataset.placement || "bottom";

  const updatePosition = () => {
    computePosition(trigger, tooltip, {
      placement,
      middleware: [
        // Flip to the opposite side when there's no room.
        flip(),
        // Slide along the axis to avoid horizontal/vertical overflow.
        shift({ padding: 10 }),
      ],
    }).then(({ x, y }) => {
      Object.assign(tooltip.style, {
        position: "fixed",
        top: `${y}px`,
        left: `${x}px`,
      });
    });
  };

  // Recalculate on scroll, resize and layout changes.
  autoUpdate(trigger, tooltip, updatePosition);
});

autoUpdate re-runs computePosition automatically on scroll, resize and element changes — you don't need any extra event listeners. The tooltip keeps its CSS hover behavior; the script only moves it to the correct place.