Coachmark
A copy-paste tooltips component in pure HTML & CSS. Zero dependencies, framework-agnostic, MIT-licensed.
TooltipsHTMLCSSany framework
NewPin items here to find them fast.
Copy into your project
HTML
<div class="nuda-stepcoach">
<span class="nuda-stepcoach__ping"></span>
<button class="nuda-stepcoach__dot" aria-describedby="stepcoach-tip-1"
aria-label="New feature"></button>
<div class="nuda-stepcoach__bubble" role="tooltip" id="stepcoach-tip-1">
<span class="nuda-stepcoach__label">New</span>
<span class="nuda-stepcoach__copy">Pin items here to find them fast.</span>
</div>
</div>CSS
/* Coachmark
Pulsing onboarding dot with an attached coachmark bubble + arrow.
Customize: --coach-accent */
.nuda-stepcoach {
--coach-accent: #e4ff54;
position: relative;
display: inline-block;
padding: 6px;
}
.nuda-stepcoach__dot {
position: relative;
display: block;
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--coach-accent);
border: none;
cursor: pointer;
z-index: 1;
box-shadow: 0 0 0 3px rgba(228, 255, 84, 0.18);
}
.nuda-stepcoach__ping {
position: absolute;
left: 6px;
top: 6px;
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--coach-accent);
animation: nuda-stepcoach-ping 1.8s ease-out infinite;
}
@keyframes nuda-stepcoach-ping {
0% { transform: scale(1); opacity: 0.55; }
100% { transform: scale(2.6); opacity: 0; }
}
.nuda-stepcoach__bubble {
position: absolute;
left: calc(100% + 12px);
top: 50%;
transform: translateY(-50%);
width: 170px;
display: flex;
flex-direction: column;
gap: 4px;
padding: 10px;
background: #111114;
border: 1px solid var(--coach-accent);
border-radius: 10px;
box-shadow:
0 14px 36px -10px rgba(0, 0, 0, 0.6),
0 0 0 4px rgba(228, 255, 84, 0.08);
animation: nuda-stepcoach-in 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.nuda-stepcoach__bubble::before {
content: "";
position: absolute;
left: -6px;
top: 50%;
transform: translateY(-50%) rotate(45deg);
width: 10px;
height: 10px;
background: #111114;
border-left: 1px solid var(--coach-accent);
border-bottom: 1px solid var(--coach-accent);
}
.nuda-stepcoach__label {
color: #09090b;
background: var(--coach-accent);
align-self: flex-start;
font-size: 0.5rem;
font-weight: 800;
letter-spacing: 0.06em;
text-transform: uppercase;
padding: 1px 6px;
border-radius: 4px;
}
.nuda-stepcoach__copy {
color: #fafafa;
font-size: 0.7rem;
line-height: 1.4;
}
@keyframes nuda-stepcoach-in {
from { opacity: 0; transform: translateY(-50%) translateX(-8px); }
to { opacity: 1; transform: translateY(-50%) translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
.nuda-stepcoach__ping,
.nuda-stepcoach__bubble { animation: none; }
}How to use Coachmark
Paste the HTML where you need it and the CSS into a global stylesheet (or a <style> tag). Every class is prefixed nuda- so it never collides with Tailwind or your own styles. Tweak the CSS custom properties to match your design system.
Works in React, Vue, Svelte, Astro, Next.js, Nuxt, Laravel Blade, Django, Rails — or a single .html file. No npm install, no build step.