Favicon nítido em 16 px: desenho, SVG e tamanhos
Favicon que se reconhece em 16 pixels: desenhe um símbolo simples, use SVG com modo escuro e gere ICO, apple-touch e ícones do manifesto com Python.
Um ícone de aba tem 16 por 16 pixels, 256 no total. É menos espaço do que uma letra de texto ocupa na tela. Quando alguém exporta a logo da empresa em 1024 pixels e usa como favicon, o navegador faz a redução, e cada pixel da aba vira a média de 4.096 pixels da imagem original. O texto desaparece, os traços finos somem e o desenho vira mancha. Nenhum algoritmo de redimensionamento resolve isso, porque o detalhe não cabe no tamanho final.
A comparação abaixo usa a logo de uma torrefação fictícia: a original, a mesma logo reduzida a 16 pixels e um símbolo desenhado para esse tamanho, os dois ampliados para dar para ver os pixels.

Comece pelo tamanho menor
Desenhe o favicon pensando em 16 pixels e depois aumente, não o contrário. Algumas regras práticas:
- Um elemento só. A inicial do nome, o símbolo principal da logo ou uma forma simples. No exemplo, ficou só a xícara; o nome e o slogan saíram.
- Fundo sólido e contraste alto. A aba pode ser clara ou escura, e o ícone fica ao lado de dezenas de outros. Um quadrado de cantos arredondados com o símbolo em cor clara se destaca nos dois temas.
- Traços grossos. Em 16 pixels, uma linha de 1 pixel some ou fica borrada. Faça os traços com pelo menos 2 pixels nesse tamanho.
- Confira no tamanho real. Abra o ícone a 100% de zoom, ao lado de outras abas. Ampliado no editor, quase tudo parece bom.
Um SVG que acompanha o modo escuro
Para navegadores atuais, o ícone pode ser um SVG. Ele fica nítido em qualquer densidade de tela, pesa pouco e aceita CSS, incluindo prefers-color-scheme. Este é o símbolo da comparação, com as cores invertidas quando o sistema está no tema escuro:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<style>
rect.fundo { fill: #5b3a24; }
.xicara { fill: #f5e6d3; stroke: #f5e6d3; }
@media (prefers-color-scheme: dark) {
rect.fundo { fill: #f5e6d3; }
.xicara { fill: #5b3a24; stroke: #5b3a24; }
}
</style>
<rect class="fundo" width="32" height="32" rx="7"/>
<path class="xicara" stroke-width="0" d="M6 10h15v6a7.5 7.5 0 0 1-15 0z"/>
<path class="xicara" fill="none" stroke-width="2.6" d="M21 12h1.5a3.2 3.2 0 0 1 0 6.4H20" style="fill:none"/>
<rect class="xicara" stroke-width="0" x="5" y="25" width="19" height="2.6" rx="1.3"/>
</svg>
Segundo o Can I use, favicon em SVG funciona no Chrome e no Edge a partir da versão 80, no Firefox a partir da 41 e no Safari a partir da 26, no Mac e no iPhone. O servidor precisa entregar o arquivo com o tipo image/svg+xml. O SVG não substitui os outros formatos: navegadores mais antigos ignoram o arquivo, e a documentação do Google para favicon na busca lista BMP, GIF, ICO, PNG, JPEG, PPM e TIFF como formatos aceitos. SVG não está na lista.
O pacote de arquivos
Com o símbolo pronto, faltam os formatos de cada lugar. Este script em Python, com a biblioteca Pillow, monta tudo a partir de um PNG de 512 pixels. Se existirem versões de 16 e 32 pixels feitas separadamente (exportadas do SVG nesse tamanho ou retocadas à mão), ele usa essas em vez de reduzir a grande:
# gerar_favicons.py: monta o pacote de ícones a partir de um PNG grande (512 px)
# e, se existir, de versões desenhadas à mão para 16 e 32 px.
from pathlib import Path
from PIL import Image
mestre = Image.open("icon-512.png").convert("RGBA")
saida = Path("public"); saida.mkdir(exist_ok=True)
def tamanho(px):
feito_a_mao = Path(f"icon-{px}-manual.png")
if feito_a_mao.exists():
return Image.open(feito_a_mao).convert("RGBA")
return mestre.resize((px, px), Image.LANCZOS)
# ICO com três tamanhos dentro do mesmo arquivo
ico = [tamanho(48), tamanho(32), tamanho(16)]
ico[0].save(saida / "favicon.ico", sizes=[(48, 48), (32, 32), (16, 16)], append_images=ico[1:])
# Atalho no iPhone/iPad: fundo opaco, sem transparência
fundo = Image.new("RGBA", (180, 180), "#4c1d95")
fundo.alpha_composite(tamanho(180))
fundo.convert("RGB").save(saida / "apple-touch-icon.png", optimize=True)
for px in (192, 512):
tamanho(px).save(saida / f"icon-{px}.png", optimize=True)
for f in sorted(saida.iterdir()):
print(f"{f.name:22} {f.stat().st_size:6} bytes")
print("tamanhos no ICO:", sorted(Image.open(saida / "favicon.ico").info["sizes"]))
Saída da execução:
apple-touch-icon.png 6619 bytes favicon.ico 3384 bytes icon-192.png 8415 bytes icon-512.png 12543 bytes icone.svg 636 bytes tamanhos no ICO: [(16, 16), (32, 32), (48, 48)]
favicon.icocom 16, 32 e 48 pixels no mesmo arquivo. É o que os navegadores pedem em/favicon.icoquando a página não declara nada, e cada um escolhe o tamanho de que precisa.apple-touch-icon.pngde 180 pixels, com fundo opaco, para o atalho na tela inicial do iPhone e do iPad. Para não depender de como cada sistema trata a transparência, o script pinta o fundo com a cor da marca.icon-192.pngeicon-512.pngpara o manifesto do app web, os dois tamanhos que o guia de manifesto do web.dev pede para instalar o site como app. O de 192 também atende a recomendação do Google de usar um ícone maior que 48 pixels.
O pacote inteiro soma cerca de 31 KB, menos do que a logo de 1024 pixels, que tem 41 KB. Uma logo exportada direto do programa de design costuma passar de 1 MB, e o navegador baixa o favicon logo na primeira visita, junto com a página. Se o site está lento, essa é uma das primeiras coisas a medir; o método está em site mais rápido: meça antes de otimizar.
Ligando tudo no HTML
<link rel="icon" href="/favicon.ico"> <link rel="icon" href="/icone.svg" type="image/svg+xml"> <link rel="apple-touch-icon" href="/apple-touch-icon.png"> <link rel="manifest" href="/manifest.webmanifest">
E o manifesto:
{
"name": "Torrefação Serra Azul",
"icons": [
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }
]
}
Com os arquivos na raiz do site, essas linhas no <head> de todas as páginas resolvem aba, favoritos e atalho no celular. Se mesmo assim o ícone não aparecer, ou aparecer o antigo, o problema está na entrega e não no desenho: caminho relativo, tipo errado ou cache. O passo a passo está em favicon que não aparece no navegador nem no Google.