Icônes dans Astro
Astro rend les composants en HTML sur le serveur ou au moment du build, ce qui convient bien aux icônes SVG : appelez la fonction de rendu dans le frontmatter, et la page reçoit du SVG inline simple, sans JavaScript côté client. Les îles et l'élément personnalisé prennent en charge les icônes qui doivent réagir.
Installation
Installez le paquet. Les icônes statiques ne nécessitent aucune intégration Astro, car glyphfox est constitué de modules ES standards qui s'exécutent dans le frontmatter. Les îles construites avec glyphfox/react, glyphfox/vue ou glyphfox/svelte nécessitent l'intégration Astro correspondante.
npm install glyphfox # only for islands npx astro add react
Les icônes dans le frontmatter
Le code du frontmatter s'exécute sur le serveur, ou au moment du build pour les pages statiques. toSvg renvoie la chaîne SVG de n'importe quel nom d'icône, et set:html l'écrit dans la page sans l'échapper :
--- 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 accepte la syntaxe complète des noms, si bien que badges, fusions et styles tiennent en une seule chaîne : toSvg('file+check@tr'), toSvg('cloud&lock:overlap'), toSvg('heart/solid').
Importer glyphfox charge toutes les icônes, mais uniquement sur le serveur ou pendant le build. Rien de tout cela n'atteint le navigateur, car le frontmatter ne s'y exécute jamais.
Un composant Icon.astro
Encapsulez l'appel dans un composant pour que les pages passent des props plutôt que des options. Le SVG est inséré directement dans le parent, sans élément conteneur :
--- 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>
Chaque svg porte les classes glyphfox et glyphfox-NAME. Le balisage inséré avec set:html ne reçoit pas les attributs qu'Astro utilise pour limiter la portée des styles des composants : ciblez-le donc avec :global() à l'intérieur d'un sélecteur parent à portée limitée, comme ci-dessus, ou laissez-le hériter de color grâce à currentColor.
Le lien ci-dessus ne contient qu'une icône, sans texte : celle-ci reçoit donc un title, qui ajoute role="img", aria-label et un <title>, et le lien en tire son nom accessible. Les icônes placées à côté d'un texte visible restent décoratives. D'autres modèles sont présentés dans le guide d'accessibilité.
Animations sans JavaScript
Le SVG peut embarquer son propre CSS, si bien que les états vivants et les morphs au survol se jouent dans du HTML statique, sans aucun script : animate avec le trigger="mount" par défaut ou avec "hover", et morphTo avec trigger="hover", qui réagit au svg et à son parent direct.
--- 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>
Comme Icon.astro n'ajoute aucun conteneur, le svg est un enfant direct du lien, et survoler n'importe quel point du lien fait se transformer la flèche. Chaque preset s'arrête sous prefers-reduced-motion ; les presets et les déclencheurs sont répertoriés dans le guide des icônes animées.
Des îles pour gérer l'état
Les icônes qui suivent un état, comme un bouton de menu qui se transforme en icône de fermeture, ont leur place dans une île. Utilisez le paquet correspondant au framework de l'île et hydratez-la avec une directive client :
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 rend d'abord les îles sur le serveur. Les composants d'icônes comme MenuIcon enregistrent leur icône lorsque votre code les utilise, mais les noms passés à MorphIcon, Icon ou morphTo sont chargés à la demande : sans registerIcons, le HTML du serveur contient donc un svg vide jusqu'à l'hydratation de l'île.
Cela fonctionne de la même façon avec glyphfox/vue et avec glyphfox/svelte, qui nécessite Svelte 5. Pour les îles situées sous la ligne de flottaison, client:visible ou client:idle retarde le téléchargement jusqu'à ce qu'il soit nécessaire. Les détails propres à chaque framework se trouvent dans les guides React, Vue et Svelte.
L'élément personnalisé
Sans framework, l'élément <glyph-fox> gère les clics, le survol et les changements de nom. Astro traite et intègre au bundle les balises <script> des composants, et n'inclut chaque script qu'une seule fois par page, même lorsque le composant apparaît plusieurs fois :
<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>
Le bouton pilote l'icône via trigger="state" et l'attribut active. Avec trigger="click", l'élément écouterait les clics sur lui-même, et un clic dans le padding du bouton basculerait aria-pressed sans déclencher le morph de l'icône.
Les éléments personnalisés restent définis pendant la navigation côté client avec le routeur des transitions de vue d'Astro : les icônes des nouvelles pages sont donc mises à niveau d'elles-mêmes. Le code qui attache des écouteurs, comme la boucle ci-dessus, ne s'exécute qu'une fois ; avec le routeur, relancez-le sur l'événement astro:page-load.
Classes Tailwind
Si le projet utilise Tailwind CSS, le plugin glyphfox dessine les icônes sous forme de masques CSS : une autre option sans JavaScript, pratique dans les templates riches en contenu. La configuration et la syntaxe des classes sont décrites dans le guide Tailwind.
<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 transmet ses props à toSvg : il accepte donc les options communes avec leurs noms en camelCase, ainsi que class et style sous forme de chaînes pour le svg. Contrairement au moteur de rendu du core, morphTo peut ici être un nom, puisque toSvg le résout.
| Option | Type | Par défaut | Description |
|---|---|---|---|
size | number, string | 24 | Largeur et hauteur ; les nombres sont en pixels. |
color | string | currentColor | Couleur principale. |
secondaryColor | string | color | Couleur du calque duotone et du remplissage plein. |
secondaryOpacity | number | 0.3 / 1 | Opacité du calque duotone ou du remplissage plein. |
weight | number | 2 | Trait de 1 à 3 sur la grille de 24, avec compensation optique en dessous de 24 px. |
absoluteWeight | boolean | false | Garde le trait à weight pixels quelle que soit la taille. |
corners | round, sharp | round | Jointures et extrémités arrondies ou vives. |
variant | outline, duotone, solid | outline | Axe de style ; solid vient des formes fermées. |
rotate | number | 0 | Rotation en degrés. |
flipX | boolean | false | Miroir horizontal. |
flipY | boolean | false | Miroir vertical. |
mirrorRtl | boolean | false | Miroir dans les mises en page de droite à gauche. |
animate | draw, pop, wiggle, spin, pulse, bounce, shake | aucun | Préréglage d'état vivant. |
trigger | mount, hover, click, state | mount | Moment où l'animation ou le morph se joue. |
active | boolean | false | L'état pour le déclencheur state. |
duration | number (ms) | selon le préréglage | Durée de l'animation ou du morph. |
delay | number (ms) | 0 | Délai de l'animation ou du morph. |
loop | boolean, number | false | Répète à l'infini ou un certain nombre de fois (spin et pulse bouclent par défaut). |
modifier | plus, minus, check, x, alert, lock, clock, sync, arrow-up, arrow-down, dot | aucun | Badge avec espace de découpe automatique. |
modifierCorner | top-left, top-right, bottom-left, bottom-right | bottom-right | Coin du badge. |
morphTo | name, data | aucun | Cible du morph ; le déclencheur décide quand elle s'affiche. |
title | string | aucun | Nom accessible : title, role img et aria-label. |
decorative | boolean | true sans title | Masque l'icône aux technologies d'assistance. |
Pièges courants
- Styles à portée limitée et set:html
- Les règles du bloc de style d'un composant ne s'appliquent pas au balisage inséré avec
set:html, car il lui manque les attributs de portée. Utilisez:global(.glyphfox)à l'intérieur d'un sélecteur à portée limitée, ou faites héritercolor. - Les noms dans les îles
MorphIcon,IconetmorphTochargent les noms à la demande. Enregistrez leurs données avecregisterIconspour que le HTML du serveur soit complet.- Déclencheurs de clic dans les boutons
trigger="click"surglyph-foxécoute les clics sur l'icône, et les clics dans le padding du bouton ne l'atteignent pas. Utiliseztrigger="state"et définissezactivedepuis le bouton.- Les noms inconnus interrompent le build
toSvglève une exception pour un nom qui n'existe pas, ce qui fait échouer un build statique et renvoie une erreur en mode serveur. Vérifiez que les noms issus du contenu figurent dans la liste des icônes, ou interceptez l'erreur lorsqu'ils proviennent de données utilisateur.- Bundles serveur sur les runtimes edge
toSvgdu point d'entrée principal place toutes les icônes dans le bundle serveur, soit environ 154 Ko minifiés. Là où la taille des fonctions est limitée, utilisezrenderToStringdeglyphfox/coreavec un import par icône, et passez les données d'icône àmorphTo.- Conteneurs et morphs au survol
- Un morph au survol réagit au svg et à son parent direct. Envelopper l'icône dans un élément supplémentaire fait de cet élément le parent : survoler le lien qui l'entoure ne déclenche alors plus le morph.
Questions fréquentes
Les icônes rendues dans le frontmatter embarquent-elles du JavaScript ?
Non. Le frontmatter s'exécute sur le serveur ou au moment du build, et la page reçoit du SVG simple. Les presets et les morphs au survol sont du CSS intégré à ce SVG. Seuls l'élément personnalisé et les îles ajoutent du code client.
Puis-je utiliser des icônes dans du contenu Markdown ou MDX ?
En MDX, importez Icon.astro et utilisez-le comme dans n'importe quel composant. Le Markdown standard ne peut pas importer de composants : rendez donc les icônes dans le layout qui entoure le contenu, ou utilisez les classes Tailwind dans du HTML brut, là où votre Markdown le permet.