Annotation Layer
CSS tooltips anchored above highlighted passages — absolute position, pseudo-element arrow, opacity on hover. Zero JavaScript.
You'll get access to the interactive demo with a free account.
This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Navigation has 36 effects, including 4 free. Explore the category →
3 usage examples



How it works
The structure relies on span.annotation-marker elements set to display: inline with position: relative, nested inside a text block. Each marker contains a span.annotation-note with position: absolute; bottom: calc(100% + 8px) — placed 8 px above the highlighted word and centered horizontally via left: 50%; transform: translateX(-50%).
Showing and hiding is driven by two CSS properties: opacity transitions from 0 to 1 and transform: scale from 0.95 to 1 via the selector .annotation-marker:hover .annotation-note, with transition: opacity .2s, transform .2s. No JavaScript event handler is needed — the entire behavior is declarative.
The downward-pointing arrow at the bottom of the tooltip is a classic ::after pseudo-element: border-color: #fbbf24 transparent transparent creates a CSS triangle at top: 100% of the bubble, centered at left: 50%.
Stacking when adjacent markers are hovered is handled by z-index: 10 on .annotation-note and pointer-events: none to prevent the active bubble from interfering with neighboring markers.
Accessibility
- No
@media (prefers-reduced-motion)in the source code —opacityandtransformtransitions run regardless of OS preferences. Add the suppression rule manually if required. - Keyboard accessibility: the effect relies on
:hoveronly — annotations are not revealed during keyboard navigation. No:focus-withinon.annotation-marker. - Text/background contrast inside the tooltip:
#1a1a2eon#fbbf24background — ratio ≈ 10:1, WCAG AA and AAA compliant. - The highlight uses a visible
border-bottomindependent of background color perception — information is not conveyed by color alone. - Screen readers can read the content of
.annotation-note(nodisplay:none), but the semantic association between marker and note is implicit — noaria-describedbyis present in the source code.
Browser compatibility
Uses only position: absolute, transform, and transition — universally supported properties. No external dependencies.
Without CSS transition support, tooltips appear and disappear instantly on hover — fully functional, just without animation.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="annotation-content">
Your text with
<span class="annotation-marker">
annotated term
<span class="annotation-note">
<span class="fn-num">Note:</span> short explanation
</span>
</span>
, rest of the text.
</div>
Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
| background in .annotation-marker | rgba(251, 191, 36, .2) | Highlight background at rest — adjust the hue and opacity to match your brand palette. |
| border-bottom in .annotation-marker | 2px solid #fbbf24 | Marker underline — align with the tooltip background color for visual consistency. |
| background in .annotation-note | #fbbf24 | Tooltip background — any opaque color; update color and the ::after arrow color accordingly. |
| color in .annotation-note | #1a1a2e | Tooltip text color — verify the WCAG contrast ratio against the chosen background (minimum 4.5:1). |
| bottom in .annotation-note | calc(100% + 8px) | Vertical gap between the bottom of the tooltip and the top of the marker — increase to calc(100% + 14px) for more breathing room. |
| transition in .annotation-note | opacity .2s, transform .2s | Appearance duration and easing — set to 0s to suppress animation (prefers-reduced-motion compatibility). |
| font-size in .annotation-note | .72rem | Tooltip text size — increase to .82rem for better readability on mobile or in high-zoom contexts. |
FAQ
hover events. On some browsers a first tap activates the tooltip, but the behavior is inconsistent. For touch, replace :hover with a JavaScript handler that toggles an .active CSS class on the marker at click.bottom: calc(100% + 8px) and no edge constraint. If your text sits near the top or side edges, the tooltip may overflow. Fix: add a media query or a small JavaScript check that switches to top: calc(100% + 8px) when the marker is too close to the upper edge..annotation-marker is independent and manages its own tooltip via pure CSS. Simultaneous hovers display multiple tooltips at once. The z-index: 10 ensures the active tooltip always renders above neighboring markers.