Custom CSS Tooltip with Transition Effects
Create a reusable tooltip component using only HTML and CSS with smooth transitions for enhanced user experience.
Code
/* Custom CSS Tooltip (HTML + CSS only)
Reusable, themeable tooltip with smooth transitions; supports hover + keyboard focus. */
:root {
--tt-bg: rgba(0, 0, 0, 0.78);
--tt-fg: #fff;
--tt-radius: 0.5rem;
--tt-pad-y: 0.4rem;
--tt-pad-x: 0.6rem;
--tt-max-w: 18rem;
--tt-offset: 0.6rem;
--tt-arrow: 0.45rem;
--tt-dur: 200ms;
--tt-ease: cubic-bezier(.2, .8, .2, 1);
--tt-z: 1000;
}
/* Tooltip container (BEM: tooltip + tooltip__content) */
.tooltip {
position: relative;
display: inline-flex; /* modern layout; keeps icon/text aligned */
align-items: center;
gap: 0.35rem;
cursor: help;
-webkit-tap-highlight-color: transparent; /* better mobile UX */
}
/* Tooltip bubble */
.tooltip__content {
/* Hidden by default (visibility avoids accidental hover/focus capture) */
visibility: hidden;
opacity: 0;
pointer-events: none;
position: absolute;
z-index: var(--tt-z);
left: 50%;
bottom: calc(100% + var(--tt-offset));
transform: translateX(-50%) translateY(0.15rem);
transform-origin: 50% 100%;
max-width: min(var(--tt-max-w), 80vw); /* responsive */
width: max-content;
background: var(--tt-bg);
color: var(--tt-fg);
border-radius: var(--tt-radius);
padding: var(--tt-pad-y) var(--tt-pad-x);
font-size: 0.875rem;
line-height: 1.25;
text-align: center;
white-space: normal;
filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.2));
transition:
opacity var(--tt-dur) var(--tt-ease),
transform var(--tt-dur) var(--tt-ease),
visibility 0s linear var(--tt-dur); /* prevents flicker on hide */
}
/* Arrow (pure CSS) */
.tooltip__content::after {
content: "";
position: absolute;
left: 50%;
top: 100%;
transform: translateX(-50%);
border: var(--tt-arrow) solid transparent;
border-top-color: var(--tt-bg);
}
/* Show on hover + keyboard focus */
.tooltip:hover .tooltip__content,
.tooltip:focus-within .tooltip__content {
visibility: visible;
opacity: 1;
transform: translateX(-50%) translateY(0);
transition-delay: 0s;
}
/* Prefer reduced motion for accessibility */
@media (prefers-reduced-motion: reduce) {
.tooltip__content { transition: none; transform: translateX(-50%); }
}
/* Fallback for older browsers without drop-shadow (keeps contrast) */
@supports not (filter: drop-shadow(0 0 0 rgba(0, 0, 0, 0.2))) {
.tooltip__content { box-shadow: 0 10px 20px rgba(0, 0, 0, 0.25); }
}
/* Example usage (HTML):
<span class="tooltip">
<button type="button" aria-describedby="tt-1">Info</button>
<span id="tt-1" class="tooltip__content" role="tooltip">Additional details shown on hover/focus.</span>
</span>
*/