CSS Anchor Positioning Polyfill

Anchoring Elements in the shadow DOM

Note: We strive to keep the polyfill up-to-date with ongoing changes to the spec, and we welcome code contributions and financial support to make that happen.

Works if anchor and target are both inside the same shadow root

With polyfill applied: Target and Anchor’s right edges line up. Target’s top edge lines up with the bottom edge of the Anchor.

Note: this will not work across shadow root boundaries. See the next demo for an example of how to use the polyfill with adopted stylesheets.

<anchor-web-component>
  <template shadowrootmode="open">
    <style>
    #my-anchor-positioning {
      anchor-name: --my-anchor-positioning;
    }

    #my-target-positioning {
      position: absolute;
      top: anchor(--my-anchor-positioning bottom);
      right: anchor(--my-anchor-positioning right, 50px);
    }
    </style>
    <div style="position: relative">
      <div id="my-target-positioning">Target</div>
      <div id="my-anchor-positioning">Anchor</div>
    </div>
  </template>
</anchor-web-component>
<script>
class AnchorDemo extends HTMLElement {
  connectedCallback() {
    window.ANCHOR_POSITIONING_POLYFILL({ roots: [this.shadowRoot] });
  }
}
customElements.define("anchor-web-component", AnchorDemo);
</script>

Works with adopted stylesheets (constructed CSSStyleSheet)

With polyfill applied: Target and Anchor's right edges line up. Target's top edge lines up with the bottom edge of the Anchor.

This demo uses new CSSStyleSheet() with replaceSync(), added to the shadow root via adoptedStyleSheets.

<!-- Load the shadow entrypoint before defining custom elements,
so the replaceSync and adoptedStyleSheets patches are installed
before any connectedCallback runs. -->
<script type="module" src="/dist/css-anchor-positioning-shadow.js"></script>

<anchor-adopted-styles></anchor-adopted-styles>
<script>
class AnchorAdoptedStyles extends HTMLElement {
  connectedCallback() {
    this.attachShadow({ mode: "open" });

    const sheet = new CSSStyleSheet();
    sheet.replaceSync(`
      .anchor {
        anchor-name: --adopted-anchor;
      }
      .target {
        position: absolute;
        right: anchor(--adopted-anchor right, 50px);
        top: anchor(--adopted-anchor bottom);
      }
    `);
    this.shadowRoot.adoptedStyleSheets = [sheet];

    this.shadowRoot.innerHTML = `
      <div style="position: relative">
        <div class="target">Target</div>
        <div class="anchor">Anchor</div>
      </div>
    `;
  }
}
</script>