Feedback

Tooltip

A short note shown while something is hovered or focused, in CSS alone, on any of its four sides.

#overlay#popover#no-js

Demo

Preview

Hover over them, or Tab to them.

Opens aboveOpens belowOpens to the leftOpens to the rightCopy the link to this page

Last edited 2 hours ago27 October 2026, 14:02 UTC by Ada.

Get it

It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.

$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/tooltip.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/tooltip.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/tooltip.qwe
view TooltipDemo() =    <div.demo-stack>        <p.demo-note>Hover over them, or Tab to them.</p>        <div.demo-row>            <Tooltip text="Opens above"><Button variant="outline">Top</Button></Tooltip>            <Tooltip text="Opens below" placement="bottom"><Button variant="outline">Bottom</Button></Tooltip>            <Tooltip text="Opens to the left" placement="left"><Button variant="outline">Left</Button></Tooltip>            <Tooltip text="Opens to the right" placement="right"><Button variant="outline">Right</Button></Tooltip>            <Tooltip text="Copy the link to this page" placement="bottom">                <Button variant="ghost" label="Copy link">⧉</Button>            </Tooltip>        </div>        <p.demo-note>Last edited <Tooltip text="27 October 2026, 14:02 UTC"><span tabindex="0"            style="text-decoration: underline dotted; cursor: help">2 hours ago</span></Tooltip> by Ada.</p>    </div>

Source

ui/tooltip.qwe
// Tooltip: a short note shown beside something while it is hovered or focused.// CSS only: it needs no script, and the pointer can move onto the note.////   <Tooltip text="Copy the link"><Button variant="ghost" label="Copy">⧉</Button></Tooltip>//   <Tooltip text="Sent to everyone on the team" placement="bottom"><span tabindex="0">12 seen</span></Tooltip>//// text: what it says (keep it short; it is plain text). placement: "top"// (default), "bottom", "left" or "right". What it wraps (children) should be// something that takes focus, such as a button or a link, so keyboard users see it// too. field: the note's id (default "tooltip-" + the text), which the wrapper's// aria-describedby points to.// For anything someone must read or click, use a Popover instead.import ui/theme.qwe use ui_clslet tooltip_css = css`.ui-tooltip { position: relative; display: inline-flex; vertical-align: middle; }.ui-tooltip-tip {  position: absolute; z-index: 50; display: none; width: max-content; max-width: min(240px, 70vw); padding: 6px 9px;  border-radius: var(--ui-radius-sm); background: var(--ui-fg); color: var(--ui-bg); box-shadow: var(--ui-shadow);  font: 500 12px/1.4 var(--ui-font); text-align: center; white-space: normal;  --ui-tooltip-gap: 8px;}.ui-tooltip-tip::before { content: ""; position: absolute; inset: calc(-1 * var(--ui-tooltip-gap)); }.ui-tooltip-tip::after { content: ""; position: absolute; width: 8px; height: 8px; background: inherit; transform: rotate(45deg); }.ui-tooltip:hover > .ui-tooltip-tip, .ui-tooltip:focus-within > .ui-tooltip-tip {  display: block; animation: ui-tooltip-in .12s ease-out .15s both;}@keyframes ui-tooltip-in { from { opacity: 0; translate: var(--ui-tooltip-from); } }.ui-tooltip-top > .ui-tooltip-tip { bottom: calc(100% + var(--ui-tooltip-gap)); left: 50%; transform: translateX(-50%); --ui-tooltip-from: 0 4px; }.ui-tooltip-bottom > .ui-tooltip-tip { top: calc(100% + var(--ui-tooltip-gap)); left: 50%; transform: translateX(-50%); --ui-tooltip-from: 0 -4px; }.ui-tooltip-left > .ui-tooltip-tip { right: calc(100% + var(--ui-tooltip-gap)); top: 50%; transform: translateY(-50%); --ui-tooltip-from: 4px 0; }.ui-tooltip-right > .ui-tooltip-tip { left: calc(100% + var(--ui-tooltip-gap)); top: 50%; transform: translateY(-50%); --ui-tooltip-from: -4px 0; }.ui-tooltip-top > .ui-tooltip-tip::after { top: 100%; left: 50%; margin: -4px 0 0 -4px; }.ui-tooltip-bottom > .ui-tooltip-tip::after { bottom: 100%; left: 50%; margin: 0 0 -4px -4px; }.ui-tooltip-left > .ui-tooltip-tip::after { left: 100%; top: 50%; margin: -4px 0 0 -4px; }.ui-tooltip-right > .ui-tooltip-tip::after { right: 100%; top: 50%; margin: -4px -4px 0 0; }@media (prefers-reduced-motion: reduce) {  .ui-tooltip:hover > .ui-tooltip-tip, .ui-tooltip:focus-within > .ui-tooltip-tip { animation: none; }}@media (hover: none) { .ui-tooltip:hover:not(:focus-within) > .ui-tooltip-tip { display: none; } }`view Tooltip(text: str, placement: str = "top", field: str? = null, class: str? = null, children) {    style global tooltip_css    let id = field ?? `tooltip-${re.replace(lower(text), "[^a-z0-9]+", "-")}`    <span class={ui_cls(["ui-tooltip", `ui-tooltip-${placement}`, class])} aria-describedby={id}>        {children}        <span.ui-tooltip-tip role="tooltip" id={id}>{text}</span>    </span>}
Thread
59Useful? Like it, or add to its thread below.

Thread 0 posts

On Tooltip: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.