A CSS tooltip displays a brief explanatory label when a visitor hovers over or focuses an icon, button, or abbreviation. Building simple tooltips in pure CSS avoids loading heavy JavaScript tooltip libraries while keeping small UI hints crisp and positioned accurately.
Wrap or attach position: relative; on the trigger element, read the hint string from data-tooltip="..." via content: attr(data-tooltip); inside ::after, and center it above the trigger using bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);.
Always reveal the tooltip on both :hover and :focus-visible so keyboard users receive the exact same hint as mouse users.
.tooltip-btn {
position: relative;
padding: 8px 14px;
background-color: #1e293b;
color: #ffffff;
border: none;
border-radius: 6px;
}
.tooltip-btn::after {
content: attr(data-tooltip);
position: absolute;
bottom: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
background-color: #0f172a;
color: #f8fafc;
padding: 6px 10px;
font-size: 0.8rem;
border-radius: 6px;
opacity: 0;
visibility: hidden;
pointer-events: none;
transition: opacity 0.15s ease;
z-index: 40;
}
.tooltip-btn:hover::after,
.tooltip-btn:focus-visible::after {
opacity: 1;
visibility: visible;
}
Keep tooltips strictly for short supplementary hints—never hide critical form errors, keyboard shortcuts, or essential instructions inside tooltips, because mobile touch visitors cannot hover easily. For accessible interactive triggers, pair aria-label or aria-describedby on the HTML button as well.
pointer-events: none on the tooltip box: Without it, hovering the invisible box can trigger flickering or block adjacent buttons.overflow: hidden cards: Clipped containers slice off tooltips sitting above top edges.white-space: nowrap on multi-sentence hints: Long descriptions shoot past viewport edges; set max-width: 220px; width: max-content; if wrapping is needed.Yes. Passing data-tooltip="..." into content: attr(data-tooltip); inside ::before or ::after works across every modern browser.
Add a ::before pseudo-element at bottom: calc(100% + 2px); left: 50%; transform: translateX(-50%); with border: 6px solid transparent; border-top-color: #0f172a;.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With
Experiment with the code from this lesson in our interactive playground.
You've completed this section! Take a quick 5-question quiz to check your understanding.