Tooltip
Description
Section titled “Description”.bp-tooltip is a CSS-only tooltip triggered by hover and :focus-within on a .bp-tooltip-wrap container. It supports four placements (top default, bottom, start, end) and is RTL-aware via CSS logical properties. No JavaScript required.
Top (default)
<span class="bp-tooltip-wrap"><button class="bp-btn bp-btn--outline">Hover me</button><span class="bp-tooltip" role="tooltip">Helpful context</span></span>All placements
<div class="demo-tooltip-grid"><span class="bp-tooltip-wrap"> <button class="bp-btn bp-btn--outline">Top</button> <span class="bp-tooltip" role="tooltip">Tooltip on top</span></span><span class="bp-tooltip-wrap"> <button class="bp-btn bp-btn--outline">Bottom</button> <span class="bp-tooltip bp-tooltip--bottom" role="tooltip">Tooltip on bottom</span></span><span class="bp-tooltip-wrap"> <button class="bp-btn bp-btn--outline">Start</button> <span class="bp-tooltip bp-tooltip--start" role="tooltip">Tooltip on start</span></span><span class="bp-tooltip-wrap"> <button class="bp-btn bp-btn--outline">End</button> <span class="bp-tooltip bp-tooltip--end" role="tooltip">Tooltip on end</span></span></div>Public API
Section titled “Public API”| Variable | Default | Description |
|---|---|---|
--tooltip-bg | --bp-color-text | Background color |
--tooltip-color | --bp-color-bg | Text color |
--tooltip-radius | --bp-radius-md | Border radius |
--tooltip-size | --bp-text-xs | Font size |
--tooltip-padding | --bp-space-1 --bp-space-2 | Padding |
--tooltip-delay | 0.15s | Show delay |
--tooltip-offset | 0.5rem | Distance from trigger |
Customization
Section titled “Customization”Custom color
<span class="bp-tooltip-wrap"><button class="bp-btn bp-btn--primary">Info</button><span class="bp-tooltip demo-tooltip--info" role="tooltip"> This action cannot be undone</span></span>Anchor Positioning (progressive enhancement)
Section titled “Anchor Positioning (progressive enhancement)”By default the tooltip uses position: absolute inside .bp-tooltip-wrap. This works everywhere but gets clipped by overflow: hidden parents.
To opt into CSS Anchor Positioning — which renders the tooltip in the browser’s top layer, above everything — set --tooltip-anchor to a unique dashed-ident on the wrapper:
Anchor Positioning (Chrome/Edge)
<span class="bp-tooltip-wrap" style="--tooltip-anchor: --tip-save"><button class="bp-btn bp-btn--primary">Save</button><span class="bp-tooltip" role="tooltip">Ctrl+S</span></span>When anchor-name is supported, the CSS automatically uses it and adds position-try-fallbacks — if the tooltip would overflow the viewport (top edge, right edge), the browser tries bottom → end → start automatically. No JS needed. In other browsers, it silently falls back to position: absolute.
Polyfill: @oddbird/css-anchor-positioning by OddBird (Miriam Suzanne’s team) adds support to Firefox and Safari today:
<script type="module"> if (!("anchorName" in document.documentElement.style)) { import("https://unpkg.com/@oddbird/css-anchor-positioning"); }</script>Placement variants
Section titled “Placement variants”| Class | Position |
|---|---|
| (none) | Top center (default) |
.bp-tooltip--bottom | Below the trigger |
.bp-tooltip--start | Inline start (left in LTR, right in RTL) |
.bp-tooltip--end | Inline end (right in LTR, left in RTL) |
Accessibility
Section titled “Accessibility”- Add
role="tooltip"to the.bp-tooltipelement. - Add
aria-describedby="<id>"on the trigger pointing to the tooltip’sidfor screen readers. - The tooltip is shown on
:focus-within— keyboard users get it automatically when focusing the trigger. - Keep tooltip text short and non-interactive — tooltips are not reachable by mouse from the bubble.
- For interactive content (links, buttons inside the tip), use a popover instead.
<span class="bp-tooltip-wrap"> <button aria-describedby="tip-save">Save</button> <span id="tip-save" class="bp-tooltip" role="tooltip">Ctrl+S</span></span>Browser APIs
Section titled “Browser APIs”| API | Availability | Used for | Without it |
|---|---|---|---|
:focus-within | Widely available Baseline 2018 | Keyboard trigger | Tooltip only shows on hover |
| CSS logical properties | Widely available Baseline 2023 | RTL placement | Use physical left/right |
| CSS Anchor Positioning | Newly available Baseline 2025 | Top-layer tooltip (opt-in) | Falls back to position: absolute |
position-try-fallbacks | Newly available Baseline 2025 | Auto-flip when near viewport edge | No auto-flip |
visibility + opacity transition | Widely available Baseline 2012 | Smooth show/hide | Instant show/hide |
Internals
Section titled “Internals”The tooltip is position: absolute inside the inline-flex wrapper. Show/hide is done via opacity + visibility transition — visibility: hidden removes it from tab order when not visible, opacity: 0 animates the fade. The delay is applied via transition-delay so the tooltip doesn’t flash on fast cursor passes. The arrow is a CSS border trick via ::after.