Ícones em HTML puro via CDN
Uma única tag script dá à página todos os ícones do glyphfox, o elemento <glyph-fox> e um runtime que transforma placeholders <i data-glyph> em SVG inline. Sem etapa de build e sem framework.
Adicione o script
O build em arquivo único traz todos os ícones, o elemento, o runtime de placeholders e o motor. Tanto o jsDelivr quanto o unpkg resolvem a URL simples do pacote para esse arquivo, dist/web/glyphfox.min.js.
<!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>
Com defer, o download não bloqueia a análise do HTML. O script roda assim que o documento termina de ser analisado, define o elemento, faz o upgrade de todo <glyph-fox> da página e substitui os placeholders.
Fixe a versão
glyphfox@1 acompanha a versão 1.x mais recente, o que é prático enquanto você prototipa. Em produção, fixe a versão exata e o arquivo, para que a página nunca mude sem você perceber e a CDN possa manter o arquivo em cache de forma permanente.
<script defer src="https://cdn.jsdelivr.net/npm/glyphfox@1.3.0/dist/web/glyphfox.min.js"></script>
Uma versão exata também permite usar Subresource Integrity: pegue o hash desse arquivo, que o jsDelivr lista para cada arquivo, e adicione integrity e crossorigin="anonymous" à tag. Um intervalo como @1 não comporta hash, porque o arquivo por trás dele muda a cada versão.
Você também pode hospedar o arquivo por conta própria. Copie node_modules/glyphfox/dist/web/glyphfox.min.js para a sua pasta pública e aponte a tag para ele: o arquivo é autossuficiente e não faz nenhuma outra requisição.
O elemento glyph-fox
Use o elemento para ícones que mudam: um nome que é trocado, um morph, um gatilho de hover ou clique, um estado. Ele lê todas as props dos próprios atributos e é redesenhado quando algum deles muda.
<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>
O atributo morph anima a troca de menu para x, um dos pares ajustados à mão. Estilização com shadow DOM, nomes de tag personalizados e gatilhos são explicados no guia de web components.
Placeholders com data-glyph
Para ícones que nunca mudam, um placeholder é mais leve que um elemento dinâmico. O runtime substitui todo elemento que tem o atributo data-glyph por SVG inline, copia a class dele para o svg e continua observando a página, então placeholders adicionados depois pelos seus scripts também são substituídos.
<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>
As props são atributos data em kebab-case: data-size, data-weight, data-variant, data-modifier, data-animate e o restante da tabela abaixo. Um aria-label no placeholder vira o título do ícone, então o svg ganha um nome acessível.
A substituição acontece uma única vez. Depois dela, o placeholder deixa de existir, então mudar os atributos data dele não tem efeito, e os listeners ligados ao <i> se perdem junto. Ligue os listeners a um elemento pai, ou use o elemento quando o ícone precisar mudar.
Com um bundler, importe glyphfox/runtime em vez do arquivo da CDN. Ele exporta replaceGlyphs e o executa ao carregar, e inclui todos os ícones, já que uma página pode pedir qualquer nome. Não carregue esse módulo direto de uma CDN: ele importa o pacote como módulos ES separados, um arquivo por ícone, o que custa centenas de requisições. O build em arquivo único já contém o mesmo runtime.
A API global
O build da CDN também define window.glyphfox com a API do core: toSvg, fuse, search, getIcon, iconNames, categories, createMorph, toDataUri, replaceGlyphs e outras funções. Ela só existe depois que o script roda, então chame a API a partir de um script de módulo colocado depois da tag, ou após o DOMContentLoaded.
<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 transforma uma string SVG em uma URL para backgrounds em CSS ou para um <img>. Uma imagem não consegue herdar o currentColor da página, então passe uma cor explícita.
const { toDataUri, toSvg } = window.glyphfox; const check = toDataUri(toSvg('check', { size: 16, color: '#16a34a' })); document.documentElement.style.setProperty('--icon-check', `url("${check}")`);
.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 é o mesmo build como módulo ES. O export padrão é o objeto da API e, assim como o arquivo clássico, ele define o elemento e executa o runtime de placeholders.
<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>
Tamanho do arquivo e quando fazer um build próprio
O arquivo único contém todos os ícones: 216,4 KB minificado, 62,4 KB com gzip. Servido por uma CDN com cache longo, é um preço justo para um protótipo, um site de documentação ou uma página que mostra muitos ícones diferentes. Para uma landing page que mostra seis, não compensa.
| Abordagem | O que é entregue | Indicado para |
|---|---|---|
| Um script da CDN | Todos os ícones, o elemento, o runtime e a API. | Protótipos, documentação, páginas com muitos ícones. |
Um bundler com glyphfox/web/element | O elemento e os ícones que você registra. | Aplicações que já têm uma etapa de build, veja tree shaking. |
| Subconjunto em CSS pela CLI | Uma folha de estilo com uma classe de máscara por ícone e nenhum JavaScript. | Sites estáticos e ícones que nunca mudam. |
| Subconjunto em sprite pela CLI | Um arquivo SVG com um símbolo por ícone. | HTML renderizado no servidor que repete os mesmos ícones, veja sprites SVG. |
npx glyphfox build home search menu loader --type css --out public npx glyphfox build home search menu loader --type sprite --out public/icons
<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>
O build em CSS desenha cada ícone como uma máscara preenchida com currentColor, então ele assume a cor do texto e o tamanho da fonte, e inclui as animações gf-spin e gf-pulse. Todo comando aceita as props compartilhadas como flags, como --weight 1.5 ou --variant duotone.
Atributos
O elemento e os placeholders leem as mesmas props, sempre em kebab-case: como atributos simples em <glyph-fox>, por exemplo size e secondary-color, e com o prefixo data- nos placeholders, por exemplo data-size e data-secondary-color. O elemento também aceita layout, gap e morph.
| Atributo | Tipo | Padrão | Descrição |
|---|---|---|---|
name | string | nenhum | A especificação do ícone: um nome, name+modifier@corner, a&b:layout ou name/variant. |
layout | overlap, side, stack, grid, orbit, badge, inside | nenhum | Layout da fusão quando o nome junta ícones com &. |
gap | number | 1 | Espaço de recorte de uma fusão, em unidades da grade. |
morph | boolean | false | Anima toda troca de name como um morph. |
size | number, string | 24 | Largura e altura; números são pixels. |
color | string | currentColor | Cor principal. |
secondary-color | string | color | Cor da camada duotone e do preenchimento sólido. |
secondary-opacity | number | 0.3 / 1 | Opacidade da camada duotone ou do preenchimento sólido. |
weight | number | 2 | Traço de 1 a 3 na grade de 24, com compensação óptica abaixo de 24 px. |
absolute-weight | boolean | false | Mantém o traço com weight pixels em qualquer tamanho. |
corners | round, sharp | round | Junções e pontas redondas ou retas. |
variant | outline, duotone, solid | outline | Eixo de estilo; o sólido vem das formas fechadas. |
rotate | number | 0 | Rotação em graus. |
flip-x | boolean | false | Espelha na horizontal. |
flip-y | boolean | false | Espelha na vertical. |
mirror-rtl | boolean | false | Espelha em layouts da direita para a esquerda. |
animate | draw, pop, wiggle, spin, pulse, bounce, shake | nenhum | Animação de estado vivo. |
trigger | mount, hover, click, state | mount | Quando a animação ou o morph acontece. |
active | boolean | false | O estado para o gatilho state. |
duration | number (ms) | por animação | Duração da animação ou do morph. |
delay | number (ms) | 0 | Atraso da animação ou do morph. |
loop | boolean, number | false | Repete para sempre ou um número de vezes (spin e pulse repetem por padrão). |
modifier | plus, minus, check, x, alert, lock, clock, sync, arrow-up, arrow-down, dot | nenhum | Selo com espaço de recorte automático. |
modifier-corner | top-left, top-right, bottom-left, bottom-right | bottom-right | Canto do selo. |
morph-to | name, data | nenhum | Destino do morph; o gatilho decide quando aparece. |
title | string | nenhum | Nome acessível: title, role img e aria-label. |
decorative | boolean | true sem title | Esconde o ícone das tecnologias assistivas. |
Armadilhas comuns
- Scripts que rodam cedo demais
- Um script clássico inline roda durante a análise do HTML, antes de um script da CDN com defer, então ali
window.glyphfoxainda é undefined. Usetype="module", já que scripts de módulo rodam depois dos scripts com defer, na ordem do documento, ou espere oDOMContentLoaded. - O módulo do runtime carregado de uma CDN
dist/runtime/auto.jsfoi feito para bundlers. Carregado direto no navegador, ele puxa o pacote um módulo por vez, um arquivo por ícone. Em páginas simples, use o build em arquivo único.- Placeholders são substituídos uma vez só
- Mudar atributos
data-*depois da substituição não tem efeito, e os listeners do placeholder são descartados. Use<glyph-fox>para ícones que mudam. - Elementos autofechados
- Em HTML,
<glyph-fox name="home" />é uma tag aberta, então o conteúdo que vem depois some dentro do elemento. Sempre escreva a tag de fechamento. - currentColor em imagens
- Um SVG carregado em um
<img>ou usado como background CSS não enxerga a cor da página. Passe uma cor paratoSvg, ou use o subconjunto em CSS, que funciona com máscaras. - Gatilhos de clique em placeholders
- Placeholders viram SVG estático. Morphs e animações de hover continuam funcionando, porque são CSS dentro do SVG, mas os gatilhos de clique e de estado precisam do elemento, que alterna os estados para você.
- Versões flutuantes em produção
glyphfox@1muda a cada versão 1.x, e um arquivo alterado quebra o hash de integridade. Fixeglyphfox@1.0.0e o caminho completo do arquivo.
Perguntas frequentes
Devo usar o elemento ou os placeholders data-glyph?
Placeholders para ícones que nunca mudam depois do carregamento: eles viram SVG inline simples, sem nenhum elemento dinâmico por trás. O elemento para ícones que trocam de nome, se transformam ou reagem a hover, clique ou estado. Os dois vêm do mesmo script e podem ser combinados na mesma página.
Funciona com HTML inserido depois, por exemplo pelo htmx?
Sim. O runtime observa o documento inteiro, então os placeholders dentro do HTML inserido são substituídos assim que chegam, e os elementos <glyph-fox> passam pelo upgrade ao serem inseridos, porque o elemento está definido para a página.