Frameworks

Icônes en HTML pur depuis un CDN

Une seule balise script donne à une page toutes les icônes glyphfox, l'élément <glyph-fox> et un runtime qui transforme les placeholders <i data-glyph> en SVG inline. Aucune étape de build, aucun framework.

Ajouter le script

Le build en fichier unique contient toutes les icônes, l'élément, le runtime des placeholders et le moteur. jsDelivr et unpkg résolvent tous deux l'URL du paquet, sans chemin, vers ce fichier : dist/web/glyphfox.min.js.

index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>My page</title>
  <script defer src="https://cdn.jsdelivr.net/npm/glyphfox@1"></script>
  <!-- or https://unpkg.com/glyphfox@1 -->
</head>
<body>
  <glyph-fox name="home"></glyph-fox>
  <i data-glyph="search" data-size="20"></i>
</body>
</html>

Avec defer, le téléchargement ne bloque pas l'analyse du HTML. Le script s'exécute une fois le document analysé, définit l'élément, met à niveau chaque <glyph-fox> de la page et remplace les placeholders.

Figer la version

glyphfox@1 suit la dernière version 1.x, ce qui est pratique pendant le prototypage. En production, figez la version exacte et le fichier : la page ne change jamais à votre insu et le CDN peut mettre le fichier en cache définitivement.

index.html
<script defer src="https://cdn.jsdelivr.net/npm/glyphfox@1.3.0/dist/web/glyphfox.min.js"></script>

Une version exacte permet aussi l'intégrité des sous-ressources (Subresource Integrity) : récupérez l'empreinte de ce fichier, que jsDelivr indique pour chaque fichier, puis ajoutez integrity et crossorigin="anonymous" à la balise. Une plage comme @1 ne peut pas porter d'empreinte, car le fichier qu'elle désigne change à chaque version.

Vous pouvez aussi l'héberger vous-même. Copiez node_modules/glyphfox/dist/web/glyphfox.min.js dans votre dossier public et faites pointer la balise vers ce fichier : il est autonome et n'effectue aucune autre requête.

L'élément glyph-fox

Utilisez l'élément pour les icônes qui changent : un nom qui varie, un morph, un déclencheur au survol ou au clic, un état. Il lit chaque prop depuis ses attributs et se redessine dès que l'un d'eux change.

menu.html
<button type="button" class="menu" aria-label="Open menu" aria-expanded="false">
  <glyph-fox name="menu" morph duration="300"></glyph-fox>
</button>

<script type="module">
  const button = document.querySelector('.menu');
  const icon = button.querySelector('glyph-fox');
  button.addEventListener('click', () => {
    const open = button.getAttribute('aria-expanded') !== 'true';
    button.setAttribute('aria-expanded', String(open));
    button.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
    icon.setAttribute('name', open ? 'x' : 'menu');
  });
</script>

L'attribut morph anime le passage de menu à x, l'une des paires ajustées à la main. Le style dans le shadow DOM, les noms de balise personnalisés et les déclencheurs sont traités dans le guide des web components.

Placeholders avec data-glyph

Pour les icônes qui ne changent jamais, un placeholder est plus léger qu'un élément dynamique. Le runtime remplace par du SVG inline chaque élément doté d'un attribut data-glyph, copie sa class sur le svg et continue d'observer la page : les placeholders ajoutés plus tard par vos scripts sont donc eux aussi remplacés.

index.html
<i data-glyph="search" data-size="20"></i>
<i data-glyph="file+check@tr" data-weight="1.5"></i>
<i data-glyph="folder" data-variant="duotone" data-secondary-color="#ff7a1a"></i>
<i data-glyph="trash" class="danger" aria-label="Delete"></i>

Les props sont des attributs data en kebab-case : data-size, data-weight, data-variant, data-modifier, data-animate et les autres du tableau ci-dessous. Un aria-label placé sur le placeholder devient le titre de l'icône : le svg reçoit ainsi un nom accessible.

Le remplacement n'a lieu qu'une fois. Le placeholder disparaît ensuite : modifier ses attributs data par la suite n'a donc aucun effet, et les écouteurs attachés au <i> disparaissent avec lui. Attachez les écouteurs à un parent, ou utilisez l'élément lorsque l'icône doit changer.

Avec un bundler, importez glyphfox/runtime au lieu du fichier du CDN. Il exporte replaceGlyphs et l'exécute au chargement, et il inclut toutes les icônes, puisqu'une page peut demander n'importe quel nom. Ne chargez pas ce module directement depuis un CDN : il importe le paquet sous forme de modules ES séparés, un fichier par icône, ce qui représente des centaines de requêtes. Le build en fichier unique contient déjà ce même runtime.

L'API globale

Le build pour CDN définit aussi window.glyphfox avec l'API principale : toSvg, fuse, search, getIcon, iconNames, categories, createMorph, toDataUri, replaceGlyphs et d'autres encore. Elle n'existe qu'une fois le script exécuté : appelez-la donc depuis un script module placé après la balise, ou après DOMContentLoaded.

icon-search.html
<input type="search" id="q" placeholder="Search icons" aria-label="Search icons">
<div id="results"></div>

<script type="module">
  const { search, toSvg } = window.glyphfox;
  const q = document.getElementById('q');
  const results = document.getElementById('results');
  q.addEventListener('input', () => {
    results.innerHTML = search(q.value, { limit: 24 })
      .map((icon) => `<button type="button" aria-label="${icon.name}">${toSvg(icon.name, { size: 28 })}</button>`)
      .join('');
  });
</script>

toDataUri transforme une chaîne SVG en URL utilisable pour les arrière-plans CSS ou un élément <img>. Une image ne peut pas hériter de currentColor depuis la page : indiquez donc une couleur explicite.

checklist.js
const { toDataUri, toSvg } = window.glyphfox;
const check = toDataUri(toSvg('check', { size: 16, color: '#16a34a' }));
document.documentElement.style.setProperty('--icon-check', `url("${check}")`);
checklist.css
.done::before {
  content: '';
  display: inline-block;
  width: 16px;
  height: 16px;
  margin-right: 6px;
  background: var(--icon-check) no-repeat center / contain;
}

dist/web/glyphfox.esm.js est le même build sous forme de module ES. Son export par défaut est l'objet de l'API et, comme le fichier classique, il définit l'élément et exécute le runtime des placeholders.

logo.html
<div id="logo"></div>

<script type="module">
  import glyphfox from 'https://cdn.jsdelivr.net/npm/glyphfox@1/dist/web/glyphfox.esm.js';

  document.getElementById('logo').innerHTML = glyphfox.toSvg('fox', { size: 48, variant: 'duotone' });
</script>

Taille du fichier et quand préférer un build

Le fichier unique contient toutes les icônes : 216,4 Ko minifié, 62,4 Ko avec gzip. Servi depuis un CDN avec une longue durée de cache, c'est un prix raisonnable pour un prototype, un site de documentation ou une page qui affiche de nombreuses icônes différentes. C'est un mauvais calcul pour une landing page qui n'en affiche que six.

ApprocheContenuIdéal pour
Un seul script depuis le CDNToutes les icônes, l'élément, le runtime et l'API.Prototypes, documentation, pages avec beaucoup d'icônes.
Un bundler avec glyphfox/web/elementL'élément et les icônes que vous enregistrez.Applications qui ont déjà une étape de build (voir tree shaking).
Sous-ensemble CSS via la CLIUne feuille de style avec une classe de masque par icône, sans JavaScript.Sites statiques et icônes qui ne changent jamais.
Sous-ensemble en sprite via la CLIUn fichier SVG avec un symbole par icône.HTML rendu côté serveur qui répète les mêmes icônes (voir sprites SVG).
terminal
npx glyphfox build home search menu loader --type css --out public
npx glyphfox build home search menu loader --type sprite --out public/icons
index.html
<link rel="stylesheet" href="/glyphfox.css">

<span class="gf gf-home" aria-hidden="true"></span>
<span class="gf gf-loader gf-spin" aria-hidden="true"></span>

Le build CSS dessine chaque icône comme un masque rempli de currentColor : elle prend donc la couleur du texte et la taille de la police. Il inclut aussi les animations gf-spin et gf-pulse. Chaque commande accepte les props communes sous forme d'options, comme --weight 1.5 ou --variant duotone.

Attributs

L'élément et les placeholders lisent les mêmes props, en kebab-case dans les deux cas : sous forme d'attributs simples sur <glyph-fox>, comme size et secondary-color, et avec le préfixe data- sur les placeholders, comme data-size et data-secondary-color. L'élément accepte aussi layout, gap et morph.

AttributTypePar défautDescription
namestringaucunLa spécification de l'icône : un nom, name+modifier@corner, a&b:layout ou name/variant.
layoutoverlap, side, stack, grid, orbit, badge, insideaucunDisposition de la fusion quand le nom combine des icônes avec &.
gapnumber1Espace de découpe d'une fusion, en unités de la grille.
morphbooleanfalseAnime chaque changement de name sous forme de morph.
sizenumber, string24Largeur et hauteur ; les nombres sont en pixels.
colorstringcurrentColorCouleur principale.
secondary-colorstringcolorCouleur du calque duotone et du remplissage plein.
secondary-opacitynumber0.3 / 1Opacité du calque duotone ou du remplissage plein.
weightnumber2Trait de 1 à 3 sur la grille de 24, avec compensation optique en dessous de 24 px.
absolute-weightbooleanfalseGarde le trait à weight pixels quelle que soit la taille.
cornersround, sharproundJointures et extrémités arrondies ou vives.
variantoutline, duotone, solidoutlineAxe de style ; solid vient des formes fermées.
rotatenumber0Rotation en degrés.
flip-xbooleanfalseMiroir horizontal.
flip-ybooleanfalseMiroir vertical.
mirror-rtlbooleanfalseMiroir dans les mises en page de droite à gauche.
animatedraw, pop, wiggle, spin, pulse, bounce, shakeaucunPréréglage d'état vivant.
triggermount, hover, click, statemountMoment où l'animation ou le morph se joue.
activebooleanfalseL'état pour le déclencheur state.
durationnumber (ms)selon le préréglageDurée de l'animation ou du morph.
delaynumber (ms)0Délai de l'animation ou du morph.
loopboolean, numberfalseRépète à l'infini ou un certain nombre de fois (spin et pulse bouclent par défaut).
modifierplus, minus, check, x, alert, lock, clock, sync, arrow-up, arrow-down, dotaucunBadge avec espace de découpe automatique.
modifier-cornertop-left, top-right, bottom-left, bottom-rightbottom-rightCoin du badge.
morph-toname, dataaucunCible du morph ; le déclencheur décide quand elle s'affiche.
titlestringaucunNom accessible : title, role img et aria-label.
decorativebooleantrue sans titleMasque l'icône aux technologies d'assistance.

Pièges courants

Scripts exécutés trop tôt
Un script classique inline s'exécute pendant l'analyse du HTML, avant un script CDN différé : window.glyphfox y est donc encore indéfini. Utilisez type="module", car les scripts module s'exécutent après les scripts différés, dans l'ordre du document, ou attendez DOMContentLoaded.
Le module runtime chargé depuis un CDN
dist/runtime/auto.js est destiné aux bundlers. Chargé directement dans le navigateur, il récupère le paquet module par module, un fichier par icône. Sur les pages HTML simples, utilisez le build en fichier unique.
Les placeholders ne sont remplacés qu'une fois
Modifier les attributs data-* après le remplacement n'a aucun effet, et les écouteurs du placeholder sont perdus. Utilisez <glyph-fox> pour les icônes qui changent.
Éléments autofermants
En HTML, <glyph-fox name="home" /> reste une balise ouvrante : le contenu qui suit disparaît donc à l'intérieur de l'élément. Écrivez toujours la balise fermante.
currentColor dans les images
Un SVG utilisé comme source d'un <img> ou comme arrière-plan CSS n'a pas accès à la couleur de la page. Passez une couleur à toSvg, ou utilisez le sous-ensemble CSS, qui fonctionne avec des masques.
Déclencheurs au clic sur les placeholders
Les placeholders deviennent du SVG statique. Les morphs au survol et les animations fonctionnent toujours, car ce sont du CSS intégré au SVG, mais les déclencheurs de clic et d'état ont besoin de l'élément, qui bascule les états pour vous.
Versions flottantes en production
glyphfox@1 évolue à chaque version 1.x, et un fichier modifié invalide l'empreinte d'intégrité. Figez glyphfox@1.0.0 et le chemin complet du fichier.

Questions fréquentes

Faut-il utiliser l'élément ou les placeholders data-glyph ?

Les placeholders pour les icônes qui ne changent jamais après le chargement : ils deviennent du simple SVG inline, sans élément dynamique derrière eux. L'élément pour les icônes qui changent de nom, se transforment ou réagissent au survol, au clic ou à un état. Les deux proviennent du même script et peuvent cohabiter sur une même page.

Est-ce que cela fonctionne avec du HTML inséré plus tard, par exemple par htmx ?

Oui. Le runtime observe tout le document : les placeholders contenus dans le HTML inséré sont donc remplacés dès leur arrivée, et les éléments <glyph-fox> sont mis à niveau dès leur insertion, puisque l'élément est défini pour la page.

Icônes de ce guide