Icons in Astro
Astro rendert Komponenten auf dem Server oder zur Build-Zeit zu HTML, und das passt gut zu SVG-Icons: Rufen Sie den Renderer im Frontmatter auf, und die Seite erhält reines Inline-SVG ohne Client-JavaScript. Islands und das Custom Element decken die Icons ab, die reagieren müssen.
Installation
Installieren Sie das Paket. Statische Icons benötigen keine Astro-Integration, weil glyphfox aus reinen ES-Modulen besteht, die im Frontmatter laufen. Islands, die mit glyphfox/react, glyphfox/vue oder glyphfox/svelte gebaut sind, benötigen die passende Astro-Integration.
npm install glyphfox # only for islands npx astro add react
Icons im Frontmatter
Code im Frontmatter läuft auf dem Server, bei statischen Seiten zur Build-Zeit. toSvg gibt für jeden Icon-Namen den SVG-String zurück, und set:html schreibt ihn ohne Escaping in die Seite:
--- import { toSvg } from 'glyphfox'; const search = toSvg('search', { size: 20 }); --- <label class="search"> <Fragment set:html={search} /> <input type="search" name="q" aria-label="Search the docs" /> </label>
toSvg versteht die vollständige Namenssyntax, sodass Badges, Fusionen und Stile in einen einzigen String passen: toSvg('file+check@tr'), toSvg('cloud&lock:overlap'), toSvg('heart/solid').
Der Import von glyphfox lädt alle Icons, allerdings nur auf dem Server oder im Build. Nichts davon erreicht den Browser, weil das Frontmatter dort nie ausgeführt wird.
Eine Icon.astro-Komponente
Kapseln Sie den Aufruf in einer Komponente, damit Seiten Props statt Optionen übergeben. Das SVG landet direkt im Elternelement, ohne Wrapper-Element:
--- import { toSvg, type SvgOptions } from 'glyphfox'; interface Props extends SvgOptions { name: string; } const { name, ...options } = Astro.props; const svg = toSvg(name, options); --- <Fragment set:html={svg} />
--- import Icon from './Icon.astro'; --- <nav class="nav"> <a href="/"><Icon name="home" size={20} /> Home</a> <a href="/docs/"><Icon name="book-open" size={20} weight={1.5} /> Docs</a> <a href="/new/"><Icon name="file+plus" size={20} title="New file" /></a> </nav> <style> .nav :global(.glyphfox) { color: #6b7280; } .nav a:hover :global(.glyphfox) { color: #111827; } </style>
Jedes svg-Element trägt die Klassen glyphfox und glyphfox-NAME. Markup, das mit set:html eingefügt wird, erhält nicht die Attribute, die Astro für das Scoping von Komponenten-Styles verwendet. Wählen Sie es daher wie oben mit :global() innerhalb eines gescopten Eltern-Selektors aus, oder lassen Sie es color über currentColor erben.
Der Icon-Link oben hat keinen Text, daher erhält sein Icon einen title: Das ergänzt role="img", aria-label und ein <title>, und der Link bezieht seinen Namen daraus. Icons neben sichtbarem Text bleiben dekorativ. Weitere Muster finden Sie in der Anleitung zur Barrierefreiheit.
Animationen ohne JavaScript
Das SVG kann sein eigenes CSS mitbringen, daher laufen lebendige Zustände und Hover-Morphs in statischem HTML ganz ohne Skript: animate mit dem Standardwert trigger="mount" oder mit "hover" sowie morphTo mit trigger="hover", das auf das svg-Element und auf sein direktes Elternelement reagiert.
--- import Icon from './Icon.astro'; --- <a class="next" href="/chapter-2/"> Next chapter <Icon name="arrow-right" morphTo="chevron-right" trigger="hover" /> </a> <p class="status"> <Icon name="loader" animate="spin" title="Building" /> Building the preview </p>
Da Icon.astro keinen Wrapper hinzufügt, ist das svg-Element ein direktes Kind des Links, und ein Hover an beliebiger Stelle über dem Link morpht den Pfeil. Jedes Preset hält bei prefers-reduced-motion an; Presets und Auslöser sind unter Animierte Icons aufgeführt.
Islands für Zustände
Icons, die einem Zustand folgen, etwa ein Menü-Button, der zu einem Schließen-Icon morpht, gehören in eine Island. Verwenden Sie das Framework-Paket der Island und hydrieren Sie sie mit einer Client-Direktive:
import { useState } from 'react'; import { MorphIcon, registerIcons } from 'glyphfox/react'; import menu from 'glyphfox/icons/menu'; import x from 'glyphfox/icons/x'; // Names passed to MorphIcon load on demand; registering them // puts the icon in the server rendered HTML. registerIcons([menu, x]); export default function MenuButton() { const [open, setOpen] = useState(false); return ( <button type="button" aria-expanded={open} aria-label={open ? 'Close menu' : 'Open menu'} onClick={() => setOpen(!open)} > <MorphIcon name={open ? 'x' : 'menu'} duration={300} /> </button> ); }
--- import MenuButton from '../components/MenuButton.jsx'; --- <header> <MenuButton client:load /> </header>
Astro rendert Islands zuerst auf dem Server. Icon-Komponenten wie MenuIcon registrieren ihr Icon, sobald Ihr Code sie verwendet, aber Namen, die an MorphIcon, Icon oder morphTo übergeben werden, werden erst bei Bedarf geladen. Ohne registerIcons enthält das Server-HTML daher ein leeres SVG, bis die Island hydriert ist.
Dasselbe funktioniert mit glyphfox/vue und mit glyphfox/svelte, das Svelte 5 voraussetzt. Bei Islands unterhalb des sichtbaren Bereichs verzögert client:visible oder client:idle den Download, bis er gebraucht wird. Details zu den Frameworks finden Sie in den Anleitungen zu React, Vue und Svelte.
Das Custom Element
Ohne Framework übernimmt das Element <glyph-fox> Klicks, Hover und Namenswechsel. Astro verarbeitet und bündelt die <script>-Tags von Komponenten und bindet jedes Skript nur einmal pro Seite ein, auch wenn die Komponente mehrfach vorkommt:
<button type="button" class="like" aria-pressed="false" aria-label="Like"> <glyph-fox name="heart" morph-to="heart/solid" trigger="state"></glyph-fox> </button> <script> import { defineGlyphFox } from 'glyphfox/web/element'; import { registerIcons } from 'glyphfox/core'; import heart from 'glyphfox/icons/heart'; registerIcons([heart]); defineGlyphFox(); for (const button of document.querySelectorAll('button.like')) { const icon = button.querySelector('glyph-fox'); button.addEventListener('click', () => { const on = button.getAttribute('aria-pressed') !== 'true'; button.setAttribute('aria-pressed', String(on)); icon.toggleAttribute('active', on); }); } </script>
Der Button steuert das Icon über trigger="state" und das Attribut active. Mit trigger="click" würde das Element nur auf Klicks auf sich selbst reagieren, und ein Klick auf das Padding des Buttons würde aria-pressed umschalten, ohne das Icon zu morphen.
Custom Elements bleiben bei clientseitiger Navigation mit dem View-Transitions-Router von Astro definiert, daher führen Icons auf neuen Seiten ihr Upgrade von selbst durch. Code, der Listener anhängt, wie die Schleife oben, läuft nur einmal; mit dem Router führen Sie ihn beim Event astro:page-load erneut aus.
Tailwind-Klassen
Ist Tailwind CSS im Projekt eingerichtet, zeichnet das glyphfox-Plugin Icons als CSS-Masken: eine weitere Option ohne JavaScript, praktisch in inhaltsreichen Templates. Einrichtung und Klassensyntax beschreibt die Tailwind-Anleitung.
<h1 class="flex items-center gap-3"> <span class="gf-rocket text-4xl text-orange-500" aria-hidden="true"></span> Launch faster </h1>
Props
Icon.astro reicht seine Props an toSvg weiter und akzeptiert daher die gemeinsamen Optionen mit ihren camelCase-Namen, dazu class und style als Strings für das svg-Element. Anders als beim Core-Renderer kann morphTo hier ein Name sein, weil toSvg ihn auflöst.
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
size | number, string | 24 | Breite und Höhe; Zahlen sind Pixel. |
color | string | currentColor | Hauptfarbe. |
secondaryColor | string | color | Farbe der Duotone-Ebene und der Solid-Füllung. |
secondaryOpacity | number | 0.3 / 1 | Deckkraft der Duotone-Ebene oder der Solid-Füllung. |
weight | number | 2 | Strichstärke von 1 bis 3 im 24er-Raster, unter 24 px optisch ausgeglichen. |
absoluteWeight | boolean | false | Hält den Strich bei jeder Größe auf weight Pixeln. |
corners | round, sharp | round | Abgerundete oder spitze Verbindungen und Enden. |
variant | outline, duotone, solid | outline | Stilachse; solid entsteht aus den geschlossenen Formen. |
rotate | number | 0 | Drehung in Grad. |
flipX | boolean | false | Horizontal spiegeln. |
flipY | boolean | false | Vertikal spiegeln. |
mirrorRtl | boolean | false | In Layouts von rechts nach links spiegeln. |
animate | draw, pop, wiggle, spin, pulse, bounce, shake | keiner | Voreinstellung für den lebendigen Zustand. |
trigger | mount, hover, click, state | mount | Wann die Animation oder der Morph abläuft. |
active | boolean | false | Der Zustand für den Auslöser state. |
duration | number (ms) | je nach Voreinstellung | Dauer der Animation oder des Morphs. |
delay | number (ms) | 0 | Verzögerung der Animation oder des Morphs. |
loop | boolean, number | false | Endlos oder eine bestimmte Anzahl von Malen wiederholen (spin und pulse laufen standardmäßig in Schleife). |
modifier | plus, minus, check, x, alert, lock, clock, sync, arrow-up, arrow-down, dot | keiner | Badge mit automatischer Aussparung. |
modifierCorner | top-left, top-right, bottom-left, bottom-right | bottom-right | Ecke des Badges. |
morphTo | name, data | keiner | Ziel des Morphs; der Auslöser bestimmt, wann es erscheint. |
title | string | keiner | Zugänglicher Name: title, role img und aria-label. |
decorative | boolean | true ohne title | Verbirgt das Icon vor assistiven Technologien. |
Stolperfallen
- Scoped Styles und set:html
- Regeln im Style-Block einer Komponente greifen nicht bei Markup, das mit
set:htmleingefügt wurde, weil ihm die Scoping-Attribute fehlen. Verwenden Sie:global(.glyphfox)innerhalb eines gescopten Selektors, oder lassen Siecolorvererben. - Namen in Islands
MorphIcon,IconundmorphToladen Namen bei Bedarf nach. Registrieren Sie deren Daten mitregisterIcons, damit das Server-HTML vollständig ist.- Klick-Auslöser in Buttons
trigger="click"aufglyph-foxlauscht auf dem Icon selbst, und Klicks auf das Padding des Buttons erreichen es nicht. Verwenden Sietrigger="state"und setzen Sieactivevom Button aus.- Unbekannte Namen stoppen den Build
toSvgwirft bei einem nicht existierenden Namen einen Fehler, der einen statischen Build abbrechen lässt und im Servermodus eine Fehlerantwort liefert. Gleichen Sie Namen aus Inhalten mit der Icon-Liste ab, oder fangen Sie den Fehler ab, wenn die Namen aus Benutzerdaten stammen.- Server-Bundles auf Edge-Runtimes
toSvgaus dem Haupteinstiegspunkt packt alle Icons ins Server-Bundle, etwa 154 KB minifiziert. Wo die Funktionsgröße begrenzt ist, verwenden SierenderToStringausglyphfox/coremit Importen pro Icon und übergeben Icon-Daten anmorphTo.- Wrapper und Hover-Morphs
- Ein Hover-Morph reagiert auf das svg-Element und auf sein direktes Elternelement. Wenn Sie das Icon in ein zusätzliches Element einpacken, wird dieses Element zum Elternelement, und ein Hover über den umgebenden Link startet den Morph nicht mehr.
Häufige Fragen
Liefern im Frontmatter gerenderte Icons JavaScript aus?
Nein. Das Frontmatter läuft auf dem Server oder zur Build-Zeit, und die Seite erhält reines SVG. Presets und Hover-Morphs sind CSS innerhalb dieses SVG. Nur Islands und das Custom Element bringen Client-Code mit.
Kann ich Icons in Markdown- oder MDX-Inhalten verwenden?
Importieren Sie in MDX Icon.astro und verwenden Sie es wie in jeder Komponente. Reines Markdown kann keine Komponenten importieren. Rendern Sie die Icons dort im Layout um den Inhalt herum, oder verwenden Sie die Tailwind-Klassen in rohem HTML, sofern Ihr Markdown das zulässt.