Description
Tooltip shows a small popover above a trigger on hover or keyboard focus. It appears after a brief delay to avoid flashing on fast cursor passes, but disappears immediately on leave so it never blocks the interface. The hover target is the wrapper element, which lets the pointer drift onto the tooltip text without flicker.
Example
Copied to clipboard
Hover or focus the button
CSS
:root {
--tt-in-dur: 150ms;
--tt-out-dur: 50ms;
--tt-scale: 0.98;
--tt-delay: 80ms;
--tt-in-ease: ease-out;
--tt-out-ease: ease-out;
--tt-bg: #ffffff;
--tt-fg: #2f2f2f;
}
.t-tt-wrap {
position: relative;
display: inline-block;
}
.t-tt {
position: absolute;
bottom: calc(100% + 8px);
left: 50%;
transform: translate(-50%, 0) scale(var(--tt-scale));
transform-origin: 50% 100%;
padding: 8px 12px;
border-radius: 8px;
background: var(--tt-bg);
color: var(--tt-fg);
white-space: nowrap;
box-shadow:
0 0 0 1px rgba(0, 0, 0, 0.06),
0 2px 6px 0 rgba(0, 0, 0, 0.05),
0 4px 42px 0 rgba(0, 0, 0, 0.06);
opacity: 0;
pointer-events: none;
/* Default rule controls the LEAVE state. transition-delay
stays unset so leaving plays without delay. */
transition:
opacity var(--tt-out-dur) var(--tt-out-ease),
transform var(--tt-out-dur) var(--tt-out-ease);
}
/* The 50ms delay belongs ONLY to the hover rule so leaving
the trigger snaps the delay back to 0 and the disappear
plays immediately. */
.t-tt-wrap:hover .t-tt,
.t-tt-trigger:focus-visible + .t-tt {
opacity: 1;
transform: translate(-50%, 0) scale(1);
transition-duration: var(--tt-in-dur);
transition-timing-function: var(--tt-in-ease);
transition-delay: var(--tt-delay);
}
@media (prefers-reduced-motion: reduce) {
.t-tt {
transition: none !important;
}
}
React
import "./tooltip.css"; // paste the CSS above
export function Tooltip() {
return (
<span className="t-tt-wrap">
<button className="t-tt-trigger" aria-describedby="my-tooltip">
Copy
</button>
<span className="t-tt" id="my-tooltip" role="tooltip">
Copied to clipboard
</span>
</span>
);
}
Variables
| Variable | Default | Notes |
|---|---|---|
--tt-in-dur | 150ms | sourced from --p17-in-dur |
--tt-out-dur | 50ms | sourced from --p17-out-dur |
--tt-scale | 0.98 | sourced from --p17-scale-from |
--tt-delay | 80ms | sourced from --p17-delay |
--tt-in-ease | ease-out | sourced from --p17-in-ease |
--tt-out-ease | ease-out | sourced from --p17-out-ease |
--tt-bg | #ffffff | sourced from --p17-bg |
--tt-fg | #2f2f2f | sourced from --p17-fg |
Credit
Adapted from Tooltip on transitions.dev by Jakub Antalik. Original source: github.com/Jakubantalik/transitions.dev.