v157 · css · anchor positioning

Working fallback today

No shipping browser implements a *-valid value yet, so this is the script that does the same job in the meantime — and, just as importantly, the code you delete once the native value lands. It is labelled as a fallback everywhere it runs; it never claims to be the native behaviour.

Probing this browser…

Anchor removal, with and without the fallback

anchor element I am anchored to it.
Anchor present. Tooltip visible.

the fallback, and what replaces it

// Today — script, because no browser parses a *-valid value yet.
const anchor = () => document.getElementById("anchor");
const tip = document.getElementById("tip");

function syncValidity() {
  const a = anchor();
  const valid = Boolean(a) && a.isConnected &&
    getComputedStyle(a).display !== "none";
  tip.hidden = !valid;
}

new MutationObserver(syncValidity).observe(document.body, {
  childList: true, subtree: true, attributes: true,
  attributeFilter: ["style", "class", "hidden"],
});

// Later — delete all of the above and write one declaration:
// .tip { position-visibility: anchor-valid; }

The fallback is deliberately narrower than the real thing. It checks isConnected and computed display; it does not reproduce the spec’s full “acceptable anchor element” test, which also covers tree-order and containing-block requirements. It also costs a subtree MutationObserver on every attribute change, which the native value does not.

why not just feature-detect and forget it

A tempting shortcut is to run the script only when the native value is missing. That works, but the detection has to name the exact value — and there are two spellings in play, the plural anchors-valid that shipped and was reverted, and the singular anchor-valid that replaced it. A check for one of them alone will be wrong in one direction or the other, so this page tests both and says which it found.

see also