About this snippet

Three inline terms each carry a tooltip that appears above the word on hover or keyboard focus. The tooltip is tethered to its trigger with CSS anchor positioning, so it follows the term wherever the text wraps, and nothing here needs JavaScript.

Each trigger declares an anchor-name and the tooltip after it points at that name with position-anchor. A positioned element uses the nearest preceding anchor with that name, so one name serves every pair, and anchor-scope on the wrapper keeps the pairs apart. position-area puts the tooltip above the trigger and position-try-fallbacks flips it below when the top of the viewport would clip it.

Anchor positioning is in Chrome, Edge, Safari 26 and Firefox 147, so current browsers all have it. The @supports block at the end catches older ones and falls back to a relative wrapper with an absolutely positioned tooltip.

Size
2.6 KB
Uses
HTML, CSS
Loads
Nothing external
Views
33
<div class="demo">
  <p>
    A layout can pin an element to another with
    <span class="pair"><button type="button" class="term" aria-describedby="tip-1">anchor-name</button><span class="tip" id="tip-1" role="tooltip">Names an element so other elements can position themselves against it.</span></span>
    on the target and
    <span class="pair"><button type="button" class="term" aria-describedby="tip-2">position-anchor</button><span class="tip" id="tip-2" role="tooltip">Tells a positioned element which named anchor to attach to.</span></span>
    on the floating part, then choose a side with
    <span class="pair"><button type="button" class="term" aria-describedby="tip-3">position-area</button><span class="tip" id="tip-3" role="tooltip">Picks the slot around the anchor, such as top, bottom, or a corner, in one keyword.</span></span>
    and let the browser handle the rest.
  </p>
  <p class="hint">Hover or tab to a term. Scroll the term to the top edge to see the tooltip flip below it.</p>
</div>
*, *::before, *::after {
  box-sizing: border-box;
}

body {
  font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  margin: 0;
  background: #f1f5f9;
  color: #0f172a;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  padding: 20px;
}

.demo {
  background: #ffffff;
  max-width: 560px;
  padding: 36px 40px;
  border-radius: 20px;
  box-shadow: 0 20px 40px -20px rgba(15, 23, 42, 0.25);
  font-size: 1.125rem;
  line-height: 1.8;
}

.demo p {
  margin: 0;
}

.demo .hint {
  margin-top: 18px;
  font-size: 0.875rem;
  color: #64748b;
}

.pair {
  anchor-scope: --term;
}

.term {
  anchor-name: --term;
  font: inherit;
  font-weight: 600;
  color: #1d4ed8;
  background: #dbeafe;
  border: 0;
  border-radius: 6px;
  padding: 0 6px;
  cursor: help;
}

.term:focus-visible {
  outline: 2px solid #1d4ed8;
  outline-offset: 2px;
}

.tip {
  position: absolute;
  position-anchor: --term;
  position-area: block-start;
  position-try-fallbacks: flip-block;
  margin: 0 0 8px;
  width: max-content;
  max-width: 240px;
  background: #0f172a;
  color: #f8fafc;
  font-size: 0.8125rem;
  line-height: 1.5;
  padding: 8px 12px;
  border-radius: 8px;
  opacity: 0;
  visibility: hidden;
  translate: 0 4px;
  transition: opacity 0.18s ease, translate 0.18s ease, visibility 0.18s;
  pointer-events: none;
  z-index: 10;
}

.term:hover + .tip,
.term:focus-visible + .tip {
  opacity: 1;
  visibility: visible;
  translate: 0 0;
}

@supports not (position-anchor: --term) {
  .pair {
    position: relative;
    display: inline-block;
  }

  .tip {
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
  }
}
Esc
↑↓ moveEnter select

Start from a template

Open an .html file, or HTML, CSS, JS, Markdown, Less or TypeScript files. You can also drop them here. Styles and scripts go into their panes.

Share

Source

Keyboard shortcuts

Save