11 / 20
All 20 in 20 Tailwind Liquid Glass Effects
- 01Tailwind Liquid Glass Card with Hover Refraction
- 02Tailwind Liquid Glass Button with Glossy Highlight
- 03Tailwind Liquid Glass Navigation Bar
- 04Tailwind Liquid Gooey Toggle Switch
- 05Tailwind Liquid Glass Modal Dialog
- 06Tailwind Liquid Glass Theme Switcher
- 07Tailwind Liquid Glass Input Form Fields
- 08Tailwind SVG Displacement Liquid Glass Background
- 09Tailwind Liquid Glass Dropdown Menu
- 10Tailwind Liquid Glass Pricing Table
- 11Tailwind Liquid Glass Tooltip Popover
- 12Tailwind Liquid Glass Audio Player UI
- 13Tailwind Liquid Glass Range Slider
- 14Tailwind Liquid Glass Toast Notification
- 15Tailwind Liquid Glass Sidebar Navigation
- 16Tailwind Liquid Glass Accordion
- 17Tailwind Liquid Glass Login Card
- 18Tailwind Liquid Glass Floating Action Button
- 19Tailwind Liquid Glass Loading Skeleton
- 20Tailwind Liquid Glass Multi-Step Form Wizard
Tailwind Liquid Glass Tooltip Popover
A capsule tooltip that frosts the text behind it instead of hiding it. The port's discipline is the pairing: every group-hover: has a group-focus-visible: twin, so the hint is reachable by keyboard — the single most commonly skipped requirement in tooltip components.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="lgt-11 grid w-full min-h-svh place-items-center px-6 py-15 font-lgt11-sans bg-[image:url('https://picsum.photos/seed/lgtip/1100/800')] bg-cover bg-center bg-fixed" aria-label="Tailwind liquid glass tooltip demo">
<p class="max-w-[44ch] text-center text-[22px] leading-loose text-white [text-shadow:0_1px_10px_rgba(0,0,0,.5)]">
Your plan renews on the
<span tabindex="0" class="group relative cursor-help font-extrabold text-lgt11-accent outline-none border-b-2 border-dotted border-white/50 focus-visible:rounded focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white">14th<span role="tooltip" class="pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 translate-y-1.5 rounded-[14px] border border-white/40 bg-white/16 px-3.25 py-2.25 text-[13px] font-semibold leading-snug text-white opacity-0 backdrop-blur-[16px] backdrop-saturate-180 shadow-[inset_0_1px_0_rgba(255,255,255,.5),0_16px_34px_-18px_rgba(0,0,0,.7)] transition-[opacity,transform,visibility] duration-250 [text-shadow:none] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:visible group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-[opacity,visibility] after:absolute after:top-full after:left-1/2 after:size-3 after:-translate-x-1/2 after:-translate-y-[5px] after:rotate-45 after:border-r after:border-b after:border-white/40 after:bg-inherit">Auto-renews · cancel anytime up to 24h before</span></span>.
You've used
<span tabindex="0" class="group relative cursor-help font-extrabold text-lgt11-accent outline-none border-b-2 border-dotted border-white/50 focus-visible:rounded focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white">68%<span role="tooltip" class="pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 translate-y-1.5 rounded-[14px] border border-white/40 bg-white/16 px-3.25 py-2.25 text-[13px] font-semibold leading-snug text-white opacity-0 backdrop-blur-[16px] backdrop-saturate-180 shadow-[inset_0_1px_0_rgba(255,255,255,.5),0_16px_34px_-18px_rgba(0,0,0,.7)] transition-[opacity,transform,visibility] duration-250 [text-shadow:none] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:visible group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-[opacity,visibility] after:absolute after:top-full after:left-1/2 after:size-3 after:-translate-x-1/2 after:-translate-y-[5px] after:rotate-45 after:border-r after:border-b after:border-white/40 after:bg-inherit">34 GB of your 50 GB quota</span></span>
of storage this cycle, and
<span tabindex="0" class="group relative cursor-help font-extrabold text-lgt11-accent outline-none border-b-2 border-dotted border-white/50 focus-visible:rounded focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white">3 seats<span role="tooltip" class="pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 translate-y-1.5 rounded-[14px] border border-white/40 bg-white/16 px-3.25 py-2.25 text-[13px] font-semibold leading-snug text-white opacity-0 backdrop-blur-[16px] backdrop-saturate-180 shadow-[inset_0_1px_0_rgba(255,255,255,.5),0_16px_34px_-18px_rgba(0,0,0,.7)] transition-[opacity,transform,visibility] duration-250 [text-shadow:none] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:visible group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-[opacity,visibility] after:absolute after:top-full after:left-1/2 after:size-3 after:-translate-x-1/2 after:-translate-y-[5px] after:rotate-45 after:border-r after:border-b after:border-white/40 after:bg-inherit">2 active, 1 pending invite</span></span>
are assigned.
</p>
</section><section class="lgt-11 grid w-full min-h-svh place-items-center px-6 py-15 font-lgt11-sans bg-[image:url('https://picsum.photos/seed/lgtip/1100/800')] bg-cover bg-center bg-fixed" aria-label="Tailwind liquid glass tooltip demo">
<p class="max-w-[44ch] text-center text-[22px] leading-loose text-white [text-shadow:0_1px_10px_rgba(0,0,0,.5)]">
Your plan renews on the
<span tabindex="0" class="group relative cursor-help font-extrabold text-lgt11-accent outline-none border-b-2 border-dotted border-white/50 focus-visible:rounded focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white">14th<span role="tooltip" class="pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 translate-y-1.5 rounded-[14px] border border-white/40 bg-white/16 px-3.25 py-2.25 text-[13px] font-semibold leading-snug text-white opacity-0 backdrop-blur-[16px] backdrop-saturate-180 shadow-[inset_0_1px_0_rgba(255,255,255,.5),0_16px_34px_-18px_rgba(0,0,0,.7)] transition-[opacity,transform,visibility] duration-250 [text-shadow:none] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:visible group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-[opacity,visibility] after:absolute after:top-full after:left-1/2 after:size-3 after:-translate-x-1/2 after:-translate-y-[5px] after:rotate-45 after:border-r after:border-b after:border-white/40 after:bg-inherit">Auto-renews · cancel anytime up to 24h before</span></span>.
You've used
<span tabindex="0" class="group relative cursor-help font-extrabold text-lgt11-accent outline-none border-b-2 border-dotted border-white/50 focus-visible:rounded focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white">68%<span role="tooltip" class="pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 translate-y-1.5 rounded-[14px] border border-white/40 bg-white/16 px-3.25 py-2.25 text-[13px] font-semibold leading-snug text-white opacity-0 backdrop-blur-[16px] backdrop-saturate-180 shadow-[inset_0_1px_0_rgba(255,255,255,.5),0_16px_34px_-18px_rgba(0,0,0,.7)] transition-[opacity,transform,visibility] duration-250 [text-shadow:none] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:visible group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-[opacity,visibility] after:absolute after:top-full after:left-1/2 after:size-3 after:-translate-x-1/2 after:-translate-y-[5px] after:rotate-45 after:border-r after:border-b after:border-white/40 after:bg-inherit">34 GB of your 50 GB quota</span></span>
of storage this cycle, and
<span tabindex="0" class="group relative cursor-help font-extrabold text-lgt11-accent outline-none border-b-2 border-dotted border-white/50 focus-visible:rounded focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white">3 seats<span role="tooltip" class="pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 translate-y-1.5 rounded-[14px] border border-white/40 bg-white/16 px-3.25 py-2.25 text-[13px] font-semibold leading-snug text-white opacity-0 backdrop-blur-[16px] backdrop-saturate-180 shadow-[inset_0_1px_0_rgba(255,255,255,.5),0_16px_34px_-18px_rgba(0,0,0,.7)] transition-[opacity,transform,visibility] duration-250 [text-shadow:none] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:visible group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-[opacity,visibility] after:absolute after:top-full after:left-1/2 after:size-3 after:-translate-x-1/2 after:-translate-y-[5px] after:rotate-45 after:border-r after:border-b after:border-white/40 after:bg-inherit">2 active, 1 pending invite</span></span>
are assigned.
</p>
</section>@import "tailwindcss";
@theme {
--color-lgt11-accent: #7fd7ea;
--color-lgt11-accent: oklch(0.85 0.13 200);
--font-lgt11-sans: 'Manrope', system-ui, sans-serif;
}@import "tailwindcss";
@theme {
--color-lgt11-accent: #7fd7ea;
--color-lgt11-accent: oklch(0.85 0.13 200);
--font-lgt11-sans: 'Manrope', system-ui, sans-serif;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-lgt11-accent: #7fd7ea;
--color-lgt11-accent: oklch(0.85 0.13 200);
--font-lgt11-sans: 'Manrope', system-ui, sans-serif;
}@import "tailwindcss";
@theme {
--color-lgt11-accent: #7fd7ea;
--color-lgt11-accent: oklch(0.85 0.13 200);
--font-lgt11-sans: 'Manrope', system-ui, sans-serif;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;800&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;800&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Every
group-hover:is typed with agroup-focus-visible:twin, which is the entire accessibility argument for this component. invisibleplusgroup-hover:visiblekeeps the bubble out of the accessibility tree when idle —opacity-0alone does not.- The arrow uses
after:bg-inherit, so retinting the bubble retints the arrow with no second value to maintain. - Three tooltips share one class string verbatim; in a component framework this is one component, and in raw HTML it is one copy-paste.
motion-reduce:narrows the transition to opacity and visibility, so the hint still appears but stops travelling.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Liquid Glass Tooltip Popover
Source: https://codefronts.com/design-styles/tailwind-liquid-glass-effects/tailwind-liquid-glass-tooltip-popover/
A capsule tooltip that frosts the text behind it instead of hiding it. The port's discipline is the pairing: every group-hover: has a group-focus-visible: twin, so the hint is reachable by keyboard — the single most commonly skipped requirement in tooltip components.
## HTML
```html
<section class="lgt-11 grid w-full min-h-svh place-items-center px-6 py-15 font-lgt11-sans bg-[image:url('https://picsum.photos/seed/lgtip/1100/800')] bg-cover bg-center bg-fixed" aria-label="Tailwind liquid glass tooltip demo">
<p class="max-w-[44ch] text-center text-[22px] leading-loose text-white [text-shadow:0_1px_10px_rgba(0,0,0,.5)]">
Your plan renews on the
<span tabindex="0" class="group relative cursor-help font-extrabold text-lgt11-accent outline-none border-b-2 border-dotted border-white/50 focus-visible:rounded focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white">14th<span role="tooltip" class="pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 translate-y-1.5 rounded-[14px] border border-white/40 bg-white/16 px-3.25 py-2.25 text-[13px] font-semibold leading-snug text-white opacity-0 backdrop-blur-[16px] backdrop-saturate-180 shadow-[inset_0_1px_0_rgba(255,255,255,.5),0_16px_34px_-18px_rgba(0,0,0,.7)] transition-[opacity,transform,visibility] duration-250 [text-shadow:none] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:visible group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-[opacity,visibility] after:absolute after:top-full after:left-1/2 after:size-3 after:-translate-x-1/2 after:-translate-y-[5px] after:rotate-45 after:border-r after:border-b after:border-white/40 after:bg-inherit">Auto-renews · cancel anytime up to 24h before</span></span>.
You've used
<span tabindex="0" class="group relative cursor-help font-extrabold text-lgt11-accent outline-none border-b-2 border-dotted border-white/50 focus-visible:rounded focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white">68%<span role="tooltip" class="pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 translate-y-1.5 rounded-[14px] border border-white/40 bg-white/16 px-3.25 py-2.25 text-[13px] font-semibold leading-snug text-white opacity-0 backdrop-blur-[16px] backdrop-saturate-180 shadow-[inset_0_1px_0_rgba(255,255,255,.5),0_16px_34px_-18px_rgba(0,0,0,.7)] transition-[opacity,transform,visibility] duration-250 [text-shadow:none] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:visible group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-[opacity,visibility] after:absolute after:top-full after:left-1/2 after:size-3 after:-translate-x-1/2 after:-translate-y-[5px] after:rotate-45 after:border-r after:border-b after:border-white/40 after:bg-inherit">34 GB of your 50 GB quota</span></span>
of storage this cycle, and
<span tabindex="0" class="group relative cursor-help font-extrabold text-lgt11-accent outline-none border-b-2 border-dotted border-white/50 focus-visible:rounded focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white">3 seats<span role="tooltip" class="pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 translate-y-1.5 rounded-[14px] border border-white/40 bg-white/16 px-3.25 py-2.25 text-[13px] font-semibold leading-snug text-white opacity-0 backdrop-blur-[16px] backdrop-saturate-180 shadow-[inset_0_1px_0_rgba(255,255,255,.5),0_16px_34px_-18px_rgba(0,0,0,.7)] transition-[opacity,transform,visibility] duration-250 [text-shadow:none] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:visible group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-[opacity,visibility] after:absolute after:top-full after:left-1/2 after:size-3 after:-translate-x-1/2 after:-translate-y-[5px] after:rotate-45 after:border-r after:border-b after:border-white/40 after:bg-inherit">2 active, 1 pending invite</span></span>
are assigned.
</p>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-lgt11-accent: #7fd7ea;
--color-lgt11-accent: oklch(0.85 0.13 200);
--font-lgt11-sans: 'Manrope', system-ui, sans-serif;
}
```Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Liquid Glass Tooltip Popover
Source: https://codefronts.com/design-styles/tailwind-liquid-glass-effects/tailwind-liquid-glass-tooltip-popover/
A capsule tooltip that frosts the text behind it instead of hiding it. The port's discipline is the pairing: every group-hover: has a group-focus-visible: twin, so the hint is reachable by keyboard — the single most commonly skipped requirement in tooltip components.
## HTML
```html
<section class="lgt-11 grid w-full min-h-svh place-items-center px-6 py-15 font-lgt11-sans bg-[image:url('https://picsum.photos/seed/lgtip/1100/800')] bg-cover bg-center bg-fixed" aria-label="Tailwind liquid glass tooltip demo">
<p class="max-w-[44ch] text-center text-[22px] leading-loose text-white [text-shadow:0_1px_10px_rgba(0,0,0,.5)]">
Your plan renews on the
<span tabindex="0" class="group relative cursor-help font-extrabold text-lgt11-accent outline-none border-b-2 border-dotted border-white/50 focus-visible:rounded focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white">14th<span role="tooltip" class="pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 translate-y-1.5 rounded-[14px] border border-white/40 bg-white/16 px-3.25 py-2.25 text-[13px] font-semibold leading-snug text-white opacity-0 backdrop-blur-[16px] backdrop-saturate-180 shadow-[inset_0_1px_0_rgba(255,255,255,.5),0_16px_34px_-18px_rgba(0,0,0,.7)] transition-[opacity,transform,visibility] duration-250 [text-shadow:none] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:visible group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-[opacity,visibility] after:absolute after:top-full after:left-1/2 after:size-3 after:-translate-x-1/2 after:-translate-y-[5px] after:rotate-45 after:border-r after:border-b after:border-white/40 after:bg-inherit">Auto-renews · cancel anytime up to 24h before</span></span>.
You've used
<span tabindex="0" class="group relative cursor-help font-extrabold text-lgt11-accent outline-none border-b-2 border-dotted border-white/50 focus-visible:rounded focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white">68%<span role="tooltip" class="pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 translate-y-1.5 rounded-[14px] border border-white/40 bg-white/16 px-3.25 py-2.25 text-[13px] font-semibold leading-snug text-white opacity-0 backdrop-blur-[16px] backdrop-saturate-180 shadow-[inset_0_1px_0_rgba(255,255,255,.5),0_16px_34px_-18px_rgba(0,0,0,.7)] transition-[opacity,transform,visibility] duration-250 [text-shadow:none] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:visible group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-[opacity,visibility] after:absolute after:top-full after:left-1/2 after:size-3 after:-translate-x-1/2 after:-translate-y-[5px] after:rotate-45 after:border-r after:border-b after:border-white/40 after:bg-inherit">34 GB of your 50 GB quota</span></span>
of storage this cycle, and
<span tabindex="0" class="group relative cursor-help font-extrabold text-lgt11-accent outline-none border-b-2 border-dotted border-white/50 focus-visible:rounded focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white">3 seats<span role="tooltip" class="pointer-events-none invisible absolute bottom-[calc(100%+12px)] left-1/2 z-5 w-max max-w-[220px] -translate-x-1/2 translate-y-1.5 rounded-[14px] border border-white/40 bg-white/16 px-3.25 py-2.25 text-[13px] font-semibold leading-snug text-white opacity-0 backdrop-blur-[16px] backdrop-saturate-180 shadow-[inset_0_1px_0_rgba(255,255,255,.5),0_16px_34px_-18px_rgba(0,0,0,.7)] transition-[opacity,transform,visibility] duration-250 [text-shadow:none] group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:visible group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-[opacity,visibility] after:absolute after:top-full after:left-1/2 after:size-3 after:-translate-x-1/2 after:-translate-y-[5px] after:rotate-45 after:border-r after:border-b after:border-white/40 after:bg-inherit">2 active, 1 pending invite</span></span>
are assigned.
</p>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-lgt11-accent: #7fd7ea;
--color-lgt11-accent: oklch(0.85 0.13 200);
--font-lgt11-sans: 'Manrope', system-ui, sans-serif;
}
```How this works
Hover is half the interaction. The rule this component exists to demonstrate: type the focus twin immediately after the hover state, every time. It is two extra variants and it is the difference between a tooltip and a mouse-only easter egg.
class="invisible opacity-0 translate-y-1.5
group-hover:visible group-hover:opacity-100 group-hover:translate-y-0
group-focus-visible:visible group-focus-visible:opacity-100
group-focus-visible:translate-y-0"invisible, not just opacity-0. A transparent element is still in the accessibility tree and still hoverable. visibility:hidden removes it from both, and transitioning visibility with a delay lets the fade finish before it disappears.
The arrow inherits. A 12px square rotated 45 degrees with bg-inherit and two matching borders. Because it inherits the bubble's tint, retinting the tooltip retints the arrow automatically — no second colour to keep in sync.
Frost, don't block. The point of a glass tooltip is that the sentence underneath stays legible; that is why the tint is 16% rather than a solid fill.
Make it yours
- Flip to a bottom tooltip by swapping
bottom-fullfortop-fulland moving the arrow to the top edge. - Add
delay-300to the show transition so quick pointer passes across a paragraph do not flicker a row of bubbles. - Widen with
max-w-[280px]for two-line hints; beyond that you want a popover, not a tooltip. - Recolour the frost from the bubble alone —
bg-inheriton the arrow follows automatically. - For rich, interactive content use the native popover API instead; a tooltip that contains links is a popover wearing the wrong role.
Gotchas — read before shipping
- A hover-only tooltip is inaccessible. If you take one rule from this collection, make it the
group-focus-visible:twin. opacity-0alone leaves the tooltip hoverable and announceable; pair it withinvisible.pointer-events-nonematters on a bubble that overlaps its trigger — without it the tooltip can capture the pointer and flicker itself away.- Transitioning
visibilityneeds the delay on the way out only. Delaying it on the way in makes the tooltip feel broken. - Tooltip text sits over unpredictable page content. Keep it full-opacity white on a tint of at least 16%.
- Do not put essential information in a tooltip. Glass or not, it is a hint layer, not a content layer.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Utilities only, no JavaScript. Where backdrop-filter is unavailable the tooltip degrades to a solid capsule with identical behaviour and positioning.