SVG Base64 não aparece? Uma correção prática pronta para engenharia
Esse problema aparece o tempo todo em projetos reais:
- Seu
img src="data:image/svg+xml;base64,..."parece válido, mas nada renderiza. - A mesma string SVG funciona em um lugar e quebra em um plano de fundo em CSS.
- O bug é difícil de perceber no code review, mas caro para depurar.
Se isso parece familiar, este guia oferece um caminho de correção repetível.
Por que isso é difícil de depurar
Quase nunca é uma única linha quebrada. Normalmente é um problema em cadeia:
- O SVG de origem já pode estar inválido.
- A codificação pode não corresponder ao contexto de destino.
- HTML, CSS e JSON exigem escapes diferentes.
- As regras de limpeza e renderização variam conforme o ambiente.
Por isso o mesmo SVG pode renderizar em um contexto e falhar em outro.
Causas mais comuns (em ordem de prioridade)
-
Prefixo MIME incorreto
Usedata:image/svg+xml;base64,oudata:image/svg+xml,. -
Fluxo de codificação Base64 incorreto
Usarbtoa(svg)diretamente pode falhar quando o SVG contém caracteres não ASCII. -
Problemas de escape entre contextos
Especialmente em CSS, caracteres como#e aspas podem quebrar o carregamento. -
Conteúdo SVG arriscado ou bloqueado
Scripts, event handlers e referências externas podem ser removidos ou bloqueados. -
Estrutura SVG quebrada
viewBoxausente, XML malformado ou tags inválidas podem impedir a renderização.
Como resolvemos isso no SVGView
Em vez de pedir para o usuário adivinhar, tratamos o problema em três camadas.
1) Camada de entrada: valide antes de importar
Em src/lib/svg/import-handler.ts, nós:
- aplicamos limite de tipo e tamanho de arquivo (até 10 MB)
- fazemos parse e validação de XML com raiz
<svg>obrigatória - retornamos erros de parse para acelerar o diagnóstico
Isso remove entrada inválida logo no começo.
2) Camada de segurança: sanitize antes da prévia
Em src/lib/svg/sanitizer.ts, removemos:
<script>- atributos
on*de evento <foreignObject>- refs externas (
href,xlink:href,src)
Isso melhora a segurança e reduz inconsistências de renderização.
3) Camada de saída: ofereça Base64 e Data URI com URL encoding
Em src/lib/svg/exporter.ts:
export function exportToDataUri(svg: string): string {
const encoded = btoa(unescape(encodeURIComponent(svg)));
return `data:image/svg+xml;base64,${encoded}`;
}
export function exportToDataUriEncoded(svg: string): string {
const encoded = encodeURIComponent(svg);
return `data:image/svg+xml,${encoded}`;
}
Assim você pode:
- escolher Base64 para compatibilidade mais segura
- escolher URL encoding para uma saída menor e legível
- sempre usar o tipo MIME correto
image/svg+xml
Qual codificação você deve usar?
- Ambiente de destino desconhecido: comece com Base64
- Precisa de string menor e legível: use URL encoding
- Uso em plano de fundo em CSS: prefira URL encoding com escape correto
Ferramentas úteis aqui:
Checklist de verificação repetível
- Confirme o prefixo:
data:image/svg+xml;base64,oudata:image/svg+xml, - Confirme a existência de uma raiz
<svg>válida e deviewBox - Confirme um fluxo seguro de codificação UTF-8
- Confirme o escape correto para CSS/JSON
- Faça a sanitização antes de exportar
- Alterne entre Base64 e URL encoding para comparar rapidamente
FAQ
Por que funciona em <img> mas falha em CSS?
Porque o parser de strings em CSS exige escapes mais rígidos. URL encoding costuma ser mais seguro nesse caso.
Mudar para image/svg+xml sempre resolve?
Não. O MIME é só uma parte. Codificação, escaping e validade do SVG ainda importam.
Data URI é sempre melhor do que arquivo SVG externo?
Não. Data URI é ótimo para arquivos pequenos embutidos na interface. Arquivos grandes ou muito reutilizados costumam funcionar melhor como arquivos externos.
Resumo
“SVG Base64 não aparece” não é um único bug. É um problema de fluxo.
Quando você padroniza o fluxo como validar -> sanitizar -> dupla codificação -> contexto correto, o problema fica previsível e administrável.