Tooltip
Small contextual labels on hover or focus, using the Popover API and CSS Anchor Positioning.
Usage
<span class="zui-tooltip">
<button class="zui-button" style="anchor-name: --tooltip-demo" data-tooltip-trigger="tooltip-demo">Hover me</button>
<span popover="manual" id="tooltip-demo" class="zui-tooltip-content zui-tooltip-placement-top" style="position-anchor: --tooltip-demo" role="tooltip">Helpful information</span>
</span>
<script>
document.querySelectorAll('[data-tooltip-trigger]').forEach((trigger) => {
const popover = document.getElementById(trigger.dataset.tooltipTrigger)
if (!popover) return
trigger.addEventListener('mouseenter', () => popover.showPopover())
trigger.addEventListener('mouseleave', () => popover.hidePopover())
trigger.addEventListener('focus', () => popover.showPopover())
trigger.addEventListener('blur', () => popover.hidePopover())
})
</script>import { Tooltip, Button } from '@mrmartineau/zui/react'
<Tooltip text="Helpful information">
<Button>Hover me</Button>
</Tooltip>---
import { Tooltip, Button } from '@mrmartineau/zui/astro'
---
<Tooltip text="Helpful information">
<Button>Hover me</Button>
</Tooltip>import { Tooltip, Button } from '@mrmartineau/zui/solid'
<Tooltip text="Helpful information">
<Button>Hover me</Button>
</Tooltip><script lang="ts">
import { Tooltip, Button } from '@mrmartineau/zui/svelte'
</script>
<Tooltip text="Helpful information">
<Button>Hover me</Button>
</Tooltip><template>
<Tooltip text="Helpful information">
<Button>Hover me</Button>
</Tooltip>
</template>
<script setup>
import { Tooltip, Button } from '@mrmartineau/zui/vue'
</script>Placement
Tooltips default to top placement. Use the placement prop (or placement class) to change direction.
<!-- Top (default) -->
<span class="zui-tooltip">
<button class="zui-button" style="anchor-name: --tt-top" data-tooltip-trigger="tt-top">Top</button>
<span popover="manual" id="tt-top" class="zui-tooltip-content zui-tooltip-placement-top" style="position-anchor: --tt-top" role="tooltip">Appears above</span>
</span>
<!-- Bottom -->
<span class="zui-tooltip">
<button class="zui-button" style="anchor-name: --tt-bottom" data-tooltip-trigger="tt-bottom">Bottom</button>
<span popover="manual" id="tt-bottom" class="zui-tooltip-content zui-tooltip-placement-bottom" style="position-anchor: --tt-bottom" role="tooltip">Appears below</span>
</span>
<!-- Left -->
<span class="zui-tooltip">
<button class="zui-button" style="anchor-name: --tt-left" data-tooltip-trigger="tt-left">Left</button>
<span popover="manual" id="tt-left" class="zui-tooltip-content zui-tooltip-placement-left" style="position-anchor: --tt-left" role="tooltip">Appears left</span>
</span>
<!-- Right -->
<span class="zui-tooltip">
<button class="zui-button" style="anchor-name: --tt-right" data-tooltip-trigger="tt-right">Right</button>
<span popover="manual" id="tt-right" class="zui-tooltip-content zui-tooltip-placement-right" style="position-anchor: --tt-right" role="tooltip">Appears right</span>
</span>
<script>
document.querySelectorAll('[data-tooltip-trigger]').forEach((trigger) => {
const popover = document.getElementById(trigger.dataset.tooltipTrigger)
if (!popover) return
trigger.addEventListener('mouseenter', () => popover.showPopover())
trigger.addEventListener('mouseleave', () => popover.hidePopover())
trigger.addEventListener('focus', () => popover.showPopover())
trigger.addEventListener('blur', () => popover.hidePopover())
})
</script>import { Tooltip, Button } from '@mrmartineau/zui/react'
<Tooltip text="Appears above">
<Button>Top</Button>
</Tooltip>
<Tooltip text="Appears below" placement="bottom">
<Button>Bottom</Button>
</Tooltip>
<Tooltip text="Appears left" placement="left">
<Button>Left</Button>
</Tooltip>
<Tooltip text="Appears right" placement="right">
<Button>Right</Button>
</Tooltip>---
import { Tooltip, Button } from '@mrmartineau/zui/astro'
---
<Tooltip text="Appears above"><Button>Top</Button></Tooltip>
<Tooltip text="Appears below" placement="bottom"><Button>Bottom</Button></Tooltip>
<Tooltip text="Appears left" placement="left"><Button>Left</Button></Tooltip>
<Tooltip text="Appears right" placement="right"><Button>Right</Button></Tooltip>import { Tooltip, Button } from '@mrmartineau/zui/solid'
<Tooltip text="Appears above">
<Button>Top</Button>
</Tooltip>
<Tooltip text="Appears below" placement="bottom">
<Button>Bottom</Button>
</Tooltip>
<Tooltip text="Appears left" placement="left">
<Button>Left</Button>
</Tooltip>
<Tooltip text="Appears right" placement="right">
<Button>Right</Button>
</Tooltip><script lang="ts">
import { Tooltip, Button } from '@mrmartineau/zui/svelte'
</script>
<Tooltip text="Appears above">
<Button>Top</Button>
</Tooltip>
<Tooltip text="Appears below" placement="bottom">
<Button>Bottom</Button>
</Tooltip>
<Tooltip text="Appears left" placement="left">
<Button>Left</Button>
</Tooltip>
<Tooltip text="Appears right" placement="right">
<Button>Right</Button>
</Tooltip><template>
<Tooltip text="Appears above">
<Button>Top</Button>
</Tooltip>
<Tooltip text="Appears below" placement="bottom">
<Button>Bottom</Button>
</Tooltip>
<Tooltip text="Appears left" placement="left">
<Button>Left</Button>
</Tooltip>
<Tooltip text="Appears right" placement="right">
<Button>Right</Button>
</Tooltip>
</template>
<script setup>
import { Tooltip, Button } from '@mrmartineau/zui/vue'
</script>Shape
Use the shape prop on Tooltip to change the corners of the tooltip: default (rounded), hard (square), soft (pill) or squircle. A squircle is a rounded square with smooth corners. Browsers without corner-shape support show normal rounded corners. Hover each button to compare.
<span class="zui-tooltip">
<button class="zui-button" style="anchor-name: --sq-tooltip-default" data-tooltip-trigger="sq-tooltip-default">Default</button>
<span popover="manual" id="sq-tooltip-default" class="zui-tooltip-content zui-tooltip-placement-top" style="position-anchor: --sq-tooltip-default" role="tooltip">Helpful information</span>
</span>
<span class="zui-tooltip zui-tooltip-shape-hard">
<button class="zui-button" style="anchor-name: --sq-tooltip-hard" data-tooltip-trigger="sq-tooltip-hard">Hard</button>
<span popover="manual" id="sq-tooltip-hard" class="zui-tooltip-content zui-tooltip-placement-top" style="position-anchor: --sq-tooltip-hard" role="tooltip">Helpful information</span>
</span>
<span class="zui-tooltip zui-tooltip-shape-soft">
<button class="zui-button" style="anchor-name: --sq-tooltip-soft" data-tooltip-trigger="sq-tooltip-soft">Soft</button>
<span popover="manual" id="sq-tooltip-soft" class="zui-tooltip-content zui-tooltip-placement-top" style="position-anchor: --sq-tooltip-soft" role="tooltip">Helpful information</span>
</span>
<span class="zui-tooltip zui-tooltip-shape-squircle">
<button class="zui-button" style="anchor-name: --sq-tooltip-squircle" data-tooltip-trigger="sq-tooltip-squircle">Squircle</button>
<span popover="manual" id="sq-tooltip-squircle" class="zui-tooltip-content zui-tooltip-placement-top" style="position-anchor: --sq-tooltip-squircle" role="tooltip">Helpful information</span>
</span>
<script>
document.querySelectorAll('[data-tooltip-trigger]').forEach((trigger) => {
const popover = document.getElementById(trigger.dataset.tooltipTrigger)
if (!popover) return
trigger.addEventListener('mouseenter', () => popover.showPopover())
trigger.addEventListener('mouseleave', () => popover.hidePopover())
trigger.addEventListener('focus', () => popover.showPopover())
trigger.addEventListener('blur', () => popover.hidePopover())
})
</script>import { Tooltip, Button } from '@mrmartineau/zui/react'
<Tooltip text="Helpful information">
<Button>Default</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="hard">
<Button>Hard</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="soft">
<Button>Soft</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="squircle">
<Button>Squircle</Button>
</Tooltip>---
import { Tooltip, Button } from '@mrmartineau/zui/astro'
---
<Tooltip text="Helpful information">
<Button>Default</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="hard">
<Button>Hard</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="soft">
<Button>Soft</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="squircle">
<Button>Squircle</Button>
</Tooltip>import { Tooltip, Button } from '@mrmartineau/zui/solid'
<Tooltip text="Helpful information">
<Button>Default</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="hard">
<Button>Hard</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="soft">
<Button>Soft</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="squircle">
<Button>Squircle</Button>
</Tooltip><script lang="ts">
import { Tooltip, Button } from '@mrmartineau/zui/svelte'
</script>
<Tooltip text="Helpful information">
<Button>Default</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="hard">
<Button>Hard</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="soft">
<Button>Soft</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="squircle">
<Button>Squircle</Button>
</Tooltip><template>
<Tooltip text="Helpful information">
<Button>Default</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="hard">
<Button>Hard</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="soft">
<Button>Soft</Button>
</Tooltip>
<Tooltip text="Helpful information" shape="squircle">
<Button>Squircle</Button>
</Tooltip>
</template>
<script setup>
import { Tooltip, Button } from '@mrmartineau/zui/vue'
</script>To make squircle the default everywhere, add zui-squircle-all to <html> — see Squircle.
Browser support
The tooltip uses the Popover API and CSS anchor positioning. The Popover API works in all current browsers. Anchor positioning needs Chrome or Edge 125, Safari 26 or Firefox 147 or later.
In older browsers, the tooltip shows in the centre of the viewport, not next to its trigger. To get the correct position in these browsers, load the CSS anchor positioning polyfill in your app.
CSS custom properties
Set these on :root, on a wrapper, or on the element. See Component custom properties.
| Property | Default | Description |
|---|---|---|
--zui-tooltip-bg |
var(--color-surface) |
Background colour |
--zui-tooltip-fg |
currentColor |
Text colour |
--zui-tooltip-radius |
var(--radius-md) |
Border radius |
--zui-tooltip-padding |
var(--space-4xs) var(--space-2xs) |
Padding |
--zui-tooltip-font-size |
var(--step--2) |
Font size |
--zui-tooltip-shadow |
var(--shadow-md) |
Box shadow |
--zui-tooltip-border |
var(--color-border) |
Border colour |
--zui-tooltip-border-width |
1px |
Border width. Set to 0 to hide |
--zui-tooltip-border-style |
var(--border-style, solid) |
Border style (solid, dashed, dotted, …) |