1 min read

Where did my arrows go? An astro-icon sprite story

Every arrow-right on this site silently vanished on desktop while arrow-left rendered fine. The culprit: SVG sprite deduplication meeting Astro island templates.

AstroTypeScript

Every pixelarticons:arrow-right on this site disappeared one day — while arrow-left kept rendering fine. No errors, no missing requests. Just empty squares.

The mechanism

astro-icon dedupes icons per page: the first render of a name emits the <symbol> definition, every later one emits a bare <use href="#...">. Document order decides who is first.

On this site, the first arrow-right lived inside the mobile side menu — an Astro island that ships its slot content in an inert <template data-astro-template> until hydration. On desktop that island never hydrates, so the symbol never enters the live DOM, and all 28 <use> references resolve to nothing.

<template data-astro-template="workPanel">
  <svg data-icon="pixelarticons:arrow-right">
    <symbol id="ai:pixelarticons:arrow-right">…</symbol>
    <use href="#ai:pixelarticons:arrow-right" />
  </svg>
</template>

<!-- everywhere else on the page -->
<svg data-icon="pixelarticons:arrow-right">
  <use href="#ai:pixelarticons:arrow-right" /> <!-- points at nothing -->
</svg>

The fix

Partial inlining can't work — inline renders still advance the per-name counter. The only consistent policy is a local Icon.astro wrapper that forces is:inline everywhere, trading a few KB of repeated (and highly compressible) SVG bodies for correctness.

Lesson: any dedup keyed on document order is unsound the moment part of your document is a template.