Home / Snippets / Color & Theming /
Glass tooltip
Frosted glass tooltip with backdrop-filter: blur and a semi-transparent oklch() background. Hover or focus to reveal.
Quick implementation
/* HTML:
<button class="gt-trigger">
Share
<span class="gt-tip" role="tooltip">Copy link to clipboard</span>
</button> */
.gt-trigger {
position: relative;
display: inline-flex;
align-items: center;
cursor: pointer;
}
.gt-tip {
position: absolute;
bottom: calc(100% + 0.625rem);
left: 50%;
transform: translateX(-50%) translateY(4px);
white-space: nowrap;
padding: 0.45rem 0.85rem;
border-radius: 0.5rem;
font-size: 0.78rem;
font-weight: 500;
color: oklch(0.93 0.01 260);
/* Frosted glass */
background: oklch(0.22 0.03 260 / 0.65);
backdrop-filter: blur(12px) saturate(1.4);
-webkit-backdrop-filter: blur(12px) saturate(1.4);
border: 1px solid oklch(0.40 0.04 260 / 0.5);
box-shadow: 0 4px 16px oklch(0 0 0 / 0.35);
pointer-events: none;
opacity: 0;
transition: opacity 0.18s ease, transform 0.18s ease;
z-index: 10;
}
/* Arrow caret */
.gt-tip::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
border: 5px solid transparent;
border-top-color: oklch(0.40 0.04 260 / 0.5);
}
.gt-trigger:hover .gt-tip,
.gt-trigger:focus-visible .gt-tip {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
@media (prefers-reduced-motion: reduce) {
.gt-tip {
transition: opacity 0.18s ease;
transform: translateX(-50%) translateY(0);
}
}
Prompt this to your LLM
Includes role, constraints, two framework variants, and edge cases to handle.
You are a senior frontend engineer building polished UI micro-interactions.
Goal: A CSS-only frosted glass tooltip that appears above a trigger element on hover and focus-visible. Uses backdrop-filter: blur for the glass effect, oklch() semi-transparent background, and a smooth fade + slide-up entrance transition.
Technical constraints:
- Position the tooltip absolutely above the trigger using bottom: calc(100% + 0.625rem) and left: 50% with transform: translateX(-50%).
- Frosted glass: background with an oklch() color at ~0.65 alpha, backdrop-filter: blur(12px) saturate(1.4), plus -webkit-backdrop-filter for Safari.
- Include a border with a semi-transparent oklch() color and a box-shadow for depth.
- Entrance: start at opacity: 0 and translateY(4px), transition to opacity: 1 and translateY(0) on hover/focus-visible.
- Add a CSS border triangle caret using ::after with border tricks pointing downward from the tooltip bottom.
- Use pointer-events: none on the tooltip so it cannot be accidentally hovered as a separate element.
- Wrap transform transition in @media (prefers-reduced-motion: reduce) — keep opacity transition, remove translateY movement.
Framework variant (pick one):
A) Vanilla HTML + CSS — tooltip span is a child of the trigger button.
B) React component — accepts label and children props; renders the tooltip via a portal to avoid overflow: hidden clipping on ancestor elements.
Edge cases to handle:
- Viewport edges: tooltip near the left or right edge should shift horizontally via clamp() or JS repositioning to stay on screen.
- backdrop-filter unsupported: fallback to a solid dark background that still looks intentional.
- Long tooltip text: add max-width and white-space: normal to prevent overflow on small screens.
- Touch devices: tooltip should also appear on :focus-visible triggered by tap, not just pointer hover.
Return HTML + CSS.
Why this matters in 2026
Tooltips are one of the most common UI patterns, yet most implementations use opaque dark boxes that feel disconnected from their surroundings. A frosted glass tooltip with backdrop-filter: blur blends into the page composition instead of sitting on top of it — it feels native to modern design systems on macOS, iOS, and the web. Since backdrop-filter is now supported in all major browsers, this is no longer an experimental flourish but a viable production baseline.
The logic
The tooltip is a child span with position: absolute, centred above its trigger via left: 50%; transform: translateX(-50%). It starts invisible at opacity: 0 and slightly offset with translateY(4px), then transitions to fully visible and in position on the :hover and :focus-visible states of the parent. The glass appearance combines a semi-transparent oklch() background with backdrop-filter: blur(12px) saturate(1.4), which blurs whatever is behind the element in the stacking context. The caret is a classic CSS border triangle on the ::after pseudo-element, coloured to match the tooltip border.
Accessibility & performance
The tooltip span carries role="tooltip", which associates it with the trigger element for screen readers — pair it with aria-describedby on the button pointing at the tooltip's id for full ARIA compliance. The pointer-events: none rule prevents the tooltip from capturing mouse events and accidentally keeping itself visible when the cursor moves away. The @media (prefers-reduced-motion: reduce) query preserves the fade while removing the vertical slide, so motion-sensitive users still see a clear tooltip appearance without any movement. backdrop-filter is a composited property and does not trigger layout — the blur effect adds visual richness with negligible performance cost on modern GPUs.