← Back to UI screens

Live: try it with the mouse and the keyboard (Tab, arrows, Escape).

ScreenshotTooltip component — mobile, minimal style
Theme

Tooltip component — mobile, minimal style

Tooltip UI component for websites and web apps, shown in Tallyfold, a fictional finance product. Shows icon buttons and a glossary term with tooltips on hover and keyboard focus, a disabled button that still explains itself, and every state (default, hover, focus-visible, open, disabled). Minimal style: cool neutrals, Inter, 8px corners and soft shadows. Comes with copyable HTML, CSS and a few lines of plain JavaScript (keyboard support and ARIA per the WAI-ARIA Authoring Practices), a live demo, and a DESIGN.md with light and dark colour tokens.

Open live HTML ↗ Download DESIGN.md
Pattern
Tooltip
Device
Mobile
Style
Minimal
Product (fictional)
Tallyfold
Category
Finance

Spec

Colours (light)
background #f5f9ff · surface #ffffff · text #1a222c · muted #5a6472 · primary #005ab0 · accent #826fd1
Colours (dark)
background #0b1017 · surface #171e27 · text #eff2f7 · muted #a9b2be · primary #59a3ff · accent #b6a8ff
Fonts
Inter (headings and body), JetBrains Mono (code) · Google Fonts, under their own licences
Light and dark
Both included; follows the system setting
ARIA pattern
Tooltip (WAI-ARIA Authoring Practices)
Keyboard
Shows on focus; Escape hides it
States
default, hover, focus-visible, open, disabled
tooltipmobilefinancetoolbarbutton

Code

Paste the HTML where the component goes, the CSS into your stylesheet and the script before </body>. The tokens block holds the light and dark colours; swap in your own.

HTML
<div class="mgd-tipbar" role="group" aria-label="Revenue chart tools">
  <span class="mgd-tip mgd-tip--start"><button class="mgd-tip__btn" type="button" aria-labelledby="tip-0"><svg class="i" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 11a8 8 0 1 0-2.3 5.7M20 4v7h-7"/></svg></button><span class="mgd-tip__bubble" role="tooltip" id="tip-0">Refresh data</span></span>
  <span class="mgd-tip"><button class="mgd-tip__btn" type="button" aria-labelledby="tip-1"><svg class="i" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 5h16l-6 7.5V19l-4 2v-8.5z"/></svg></button><span class="mgd-tip__bubble" role="tooltip" id="tip-1">Filter by plan</span></span>
  <span class="mgd-tip"><button class="mgd-tip__btn" type="button" aria-labelledby="tip-2"><svg class="i" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 10h18M8 3v4M16 3v4"/></svg></button><span class="mgd-tip__bubble" role="tooltip" id="tip-2">Change date range</span></span>
  <span class="mgd-tip"><button class="mgd-tip__btn" type="button" aria-labelledby="tip-3" aria-disabled="true"><svg class="i" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 4v12M7 11l5 5 5-5M4 20h16"/></svg></button><span class="mgd-tip__bubble" role="tooltip" id="tip-3">Export CSV (needs the Growth plan)</span></span>
</div>
<p class="mgd-tip-copy">Your <span class="mgd-tip"><button class="mgd-tip__term" type="button" aria-describedby="tip-mrr">MRR</button><span class="mgd-tip__bubble" role="tooltip" id="tip-mrr">Monthly recurring revenue: active subscriptions, normalised to one month.</span></span> grew 4.2% in October.</p>
CSS
/* Tokens (light + dark) */
:root{--bg:#f5f9ff;--surface:#ffffff;--border:#cfd9e6;--text:#1a222c;--muted:#5a6472;--primary:#005ab0;--on-primary:#ffffff;--accent:#826fd1;--font-h:"Inter",Georgia,serif;--font-b:"Inter",system-ui,sans-serif;--hw:600;
--c-bw:1px;--c-line:var(--border);--c-r:8px;--c-pill:8px;--c-sh:0 1px 2px rgb(0 0 0 / .06);--c-pop:0 12px 32px rgb(0 0 0 / .14);--c-tt:none;--c-ls:0;--c-fw:500;--c-fs:14px;--c-ring:2px solid var(--primary);--c-ind:2px;color-scheme:light}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--bg:#0b1017;--surface:#171e27;--border:#2c343e;--text:#eff2f7;--muted:#a9b2be;--primary:#59a3ff;--on-primary:#111111;--accent:#b6a8ff;color-scheme:dark}
}
:root[data-theme="dark"]{--bg:#0b1017;--surface:#171e27;--border:#2c343e;--text:#eff2f7;--muted:#a9b2be;--primary:#59a3ff;--on-primary:#111111;--accent:#b6a8ff;color-scheme:dark}

/* Component */
.mgd-sr{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.mgd-tipbar{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding-top:44px}
.mgd-tip{position:relative;display:inline-flex}
.mgd-tip__btn{width:42px;height:42px;display:inline-grid;place-items:center;border:var(--c-bw) solid var(--c-line);border-radius:var(--c-pill);background:var(--surface);color:var(--text);box-shadow:var(--c-sh);cursor:pointer;transition:background-color .12s}
.mgd-tip__btn:hover,.mgd-tip__btn.is-hover{background:color-mix(in oklab,var(--primary) 10%,var(--surface))}
.mgd-tip__btn:focus-visible,.mgd-tip__btn.is-focus{outline:var(--c-ring);outline-offset:2px}
.mgd-tip__btn[aria-disabled="true"],.mgd-tip__btn.is-off{opacity:.45;cursor:not-allowed;box-shadow:none}
.mgd-tip__term{border:0;padding:0;background:none;color:inherit;font:inherit;cursor:help;text-decoration:underline dotted;text-underline-offset:4px}
.mgd-tip__term:focus-visible{outline:var(--c-ring);outline-offset:2px;border-radius:2px}
.mgd-tip__bubble{position:absolute;z-index:10;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);width:max-content;max-width:240px;padding:7px 10px;border-radius:var(--c-r);background:var(--text);color:var(--bg);font:500 13px/1.35 var(--font-b);letter-spacing:0;text-transform:none;box-shadow:var(--c-pop);opacity:0;visibility:hidden;transition:opacity .12s .15s,visibility 0s .27s;pointer-events:none}
.mgd-tip__bubble::after{content:"";position:absolute;top:100%;left:50%;margin-left:-5px;border:5px solid transparent;border-top-color:var(--text)}
.mgd-tip--start .mgd-tip__bubble{left:0;transform:none}
.mgd-tip--start .mgd-tip__bubble::after{left:21px}
.mgd-tip:hover .mgd-tip__bubble,.mgd-tip:focus-within .mgd-tip__bubble,.mgd-tip.is-open .mgd-tip__bubble{opacity:1;visibility:visible;transition-delay:.15s,0s;pointer-events:auto}
.mgd-tip.is-dismissed .mgd-tip__bubble{opacity:0;visibility:hidden}
.mgd-tip-copy{margin:22px 0 0;max-width:58ch;font-size:15px}
.mgd-tip-copy .mgd-tip__bubble{white-space:normal}
@media (prefers-reduced-motion:reduce){.mgd-tip,.mgd-tip *{transition:none!important;animation-duration:2.4s!important}}
JavaScript
document.querySelectorAll(".mgd-tip").forEach(function (tip) {
  tip.addEventListener("keydown", function (e) { if (e.key === "Escape") tip.classList.add("is-dismissed"); });
  tip.addEventListener("mouseleave", function () { tip.classList.remove("is-dismissed"); });
  tip.addEventListener("focusout", function () { tip.classList.remove("is-dismissed"); });
});
document.addEventListener("keydown", function (e) { if (e.key === "Escape") document.querySelectorAll(".mgd-tip:hover").forEach(function (t) { t.classList.add("is-dismissed"); }); });
document.querySelectorAll('.mgd-tip__btn[aria-disabled="true"]').forEach(function (b) { b.addEventListener("click", function (e) { e.preventDefault(); }); });

DESIGN.md

Component section (states, ARIA, keyboard)
## Component: Tooltip

A short text label that appears on hover and on keyboard focus, for icon buttons and terms that need a hint.

- **Pattern:** WAI-ARIA Authoring Practices, Tooltip (https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/)
- **Roles and attributes:** The tooltip has role="tooltip" and the trigger points to it with aria-describedby (or aria-labelledby for an icon-only button). It shows on hover and focus, stays while hovered, and Escape hides it without moving focus.
- **States drawn:** default, hover, focus-visible, open, disabled
- **Focus:** a visible `:focus-visible` outline (2px solid primary), never removed
- **Style knobs (minimal):** border 1px, corners 8px, shadow `0 1px 2px rgb(0 0 0 / .06)`, labels sentence case
- **Motion:** transitions are short (≤160ms) and switched off under `prefers-reduced-motion: reduce`
- **Code:** HTML + CSS + a few lines of plain JavaScript (no libraries); colours come only from the tokens above, so light and dark both work

### Keyboard
- **Tab:** focus a trigger to show its tooltip
- **Escape:** hide the tooltip, keep focus

### Licence
Original Made Good Designs code: free to use and adapt in any project, including commercial ones, with no credit needed. Fonts are Google Fonts under their own licences.
AI

Build this with your AI

Fonts: Inter (Google Fonts)

Writing about this component?

More tooltip components

Tooltip component — web, minimal (Tallyfold)
web · minimal
Tooltip component — mobile, editorial (Tallyfold)
mobile · editorial
Tooltip component — mobile, brutalist (Tallyfold)
mobile · brutalist
Tooltip component — mobile, luxury (Tallyfold)
mobile · luxury
Tooltip component — mobile, playful (Tallyfold)
mobile · playful
Tooltip component — mobile, corporate (Tallyfold)
mobile · corporate
Tooltip component — mobile, retro (Tallyfold)
mobile · retro
Tooltip component — mobile, monochrome (Tallyfold)
mobile · monochrome
Building with an AI coding agent? Every screen here is also in the free Made Good Designs MCP server: ask Claude, Cursor or ChatGPT to search_ui_screens (e.g. “billing settings, editorial style”), get_ui_flow for a whole journey, and get_ui_screen_code to pull the HTML and DESIGN.md straight into your project.

Save to board