v138 · css

Callout Arrow

A speech bubble whose arrow automatically flips direction using @container anchored(fallback). When the callout flips above the anchor, the arrow points down. When it flips inline, the arrow points sideways. No JavaScript reads of position — the container query fires on the element's own layout fallback state.

Feature detection: checking…
Drag the button to any corner — arrow and callout colour update automatically default position
↖ drag here
↗ drag here
↙ drag here
↘ drag here
CSS auto-positioned callout

The arrow direction and border colour change based on which position-try-fallbacks the engine applied.

Drag the button to push the callout to different edges
Detected fallback:
default (below ↓)
flip-block (above ↑)
flip-inline (right →)
both (corner)

Arrow direction gallery

Each callout style is activated by @container anchored(…) — the CSS rule below shows what fires for each fallback:

/*
  @container anchored(fallback) fires on the positioned element
  itself — querying its own layout fallback state.
*/

/* Default: callout is below anchor → arrow points UP */
.callout::before {
  border-bottom-color: var(--border-black);
  top: -16px;
}

/* flip-block applied → callout moved above → arrow points DOWN */
@container anchored(flip-block) {
  .callout::before {
    border-bottom-color: transparent;
    border-top-color: var(--border-black);
    top: auto;
    bottom: -16px;
  }
  /* Also restyle the callout itself */
  .callout { border-color: var(--accent-blue); }
}

/* flip-inline applied → callout moved right → arrow points LEFT */
@container anchored(flip-inline) {
  .callout::before {
    border-right-color: var(--border-black);
    left: -16px;
    top: 50%;
  }
  .callout { border-color: var(--accent-emerald); }
}

/*
  No JavaScript needed to detect which fallback was applied.
  The container query fires automatically based on layout state.
*/

see also