Capítulo 35
SVG
6 min de leitura 1.160 palavras 2 gravuras
Esta é o capítulo 35 de 52 do volume Aprenda a Web. O projeto-fio é a Oficina Costeira, um coletivo fictício de design em João Pessoa. O exemplo está em exemplos/35-svg/. Em cada capítulo: leia, copie, mude uma coisa, preveja, recarregue e confira.
O que você vai aprender
- Ler SVG como código XML, não só como “figura”.
- Usar
viewBoxpara escalar sem distorcer. - Colar o SVG no HTML (inline) e estilizar no CSS.
- Pintar com
currentColorjunto da cor do texto. - Dar nome acessível à marca.
- Evitar SVG de foto e arquivo sujo de editor.
SVG é texto
SVG descreve formas com tags. Você abre no editor e lê. rect, circle e path são os mais comuns. fill pinta o interior. stroke desenha o contorno.
<svg width="120" height="120" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg">
<circle cx="60" cy="60" r="48" fill="#0b4f6c"/>
</svg>
cx e cy são o centro. r é o raio. Salve como marca.svg em assets/imagens/. Ligue com img ou cole no HTML no próximo capítulo.
Copie. Mude fill para #c45c26. Preveja a laranja da Oficina. Recarregue o arquivo no navegador.
Erro comum: exportar SVG e tratar como PNG: abrir no raster, salvar de novo. O vetor vira pixels. Edite o XML ou o arquivo no editor vetorial.
viewBox
viewBox="0 0 120 120" diz o sistema de coordenadas interno: origem no canto, largura 120, altura 120. width e height no HTML/CSS são o tamanho na página. O desenho escala junto.
Sem viewBox, o recorte pode cortar ou ignorar a escala. Com viewBox e width="100%", a marca cresce na coluna.
.marca {
width: 6rem;
height: auto;
display: block;
}
Quatro números: mínimo x, mínimo y, largura, altura. Não são pixels da tela. São unidades do desenho. Se o círculo vai até 108 e o viewBox é 0 0 100 100, a borda some.
Mude o viewBox para 0 0 60 60. Preveja um zoom no canto. Recarregue. Volte aos 120.
Inline no HTML
Colar o SVG no body mistura o desenho na árvore. O CSS da página alcança fill e :hover. O xmlns pode sair quando o SVG vive dentro de HTML5.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Marca — Oficina Costeira</title>
<link rel="stylesheet" href="assets/stylesheets/main.css">
</head>
<body>
<a class="brand" href="index.html">
<svg class="marca" viewBox="0 0 120 120" width="48" height="48" role="img" aria-labelledby="marca-titulo">
<title id="marca-titulo">Oficina Costeira</title>
<circle class="marca-disco" cx="60" cy="60" r="48"/>
</svg>
Oficina Costeira
</a>
</body>
</html>
.marca-disco {
fill: currentColor;
}
.brand {
color: #0b4f6c;
}
.brand:hover,
.brand:focus-visible {
color: #c45c26;
}
O disco herda a cor do link. Um atributo de apresentação como fill pode ser sobrescrito por uma regra CSS que selecione a forma. Um estilo no atributo style tem prioridade maior. Prefira controlar a cor em um só lugar. Prefira forma sem fill no XML quando quiser currentColor.
Copie o bloco. Mude color do .brand para #c45c26. Preveja disco e texto laranja juntos. Recarregue. Sem currentColor no fill, só o texto mudaria.

currentColor
currentColor é a cor computada de color. Ícone e texto pintam juntos. Hover no link muda os dois. Foco também, se :focus-visible altera color.
Não use currentColor em foto mascarada. Use em traço, disco e letra da marca.
Se o SVG entra por img, o CSS da página não pinta o interior. img é caixa fechada. Para currentColor, cole inline ou use mask em CSS avançado. Neste volume, inline.
Acessível
SVG decorativo ao lado de um texto visível: aria-hidden="true". SVG que é a única marca: role="img" e <title> (e aria-labelledby apontando para o id do título).
img src="marca.svg" usa alt, como qualquer imagem. Os dois caminhos não se misturam: ou alt no img, ou title no SVG inline.
Limpe o arquivo exportado. Editores metem id aleatório, comentários e casas decimais. Menos código, menos peso. SVGOMG ou equivalente.
Erro comum: dez SVGs inline idênticos com os mesmos id de title. IDs duplicados quebram o rótulo. Ou use img, ou um symbol com use (próximo passo, não obrigatório agora).
O que não fazer com SVG
Não converta fotografia da orla em SVG de mil path. O arquivo incha e o processador sofre. JPG continua certo para foto.
Não anime o SVG em loop sem prefers-reduced-motion. O mesmo combinado do capítulo 34 vale para fill e transform no círculo.
Não publique o SVG com dados da sua máquina no comentário do editor. O exemplo da Oficina é fictício; metadados pessoais também não entram.
Abra assets/imagens/marca.svg do exemplo. Leia o viewBox. Mude r no círculo. Preveja um disco menor. Recarregue.
fill no CSS vence fill="" no XML. Se a marca “não muda de cor”, procure o atributo no SVG e apague. stroke: currentColor pinta o traço da mesma forma.
Um path longo copiado de um editor pode ter transformações internas. viewBox errado corta o traço. Ajuste o viewBox até a marca caber com margem, em vez de scale no CSS.
Não misture xlink:href antigo com href novo sem testar. Nos SVG deste volume, formas simples não precisam de image externa. Se precisar, o arquivo externo é mais um pedido no Rede.

Hover e redução no traço
Com o SVG inline, :hover no a muda color e o disco acompanha. Não precisa de JavaScript. O anel de :focus-visible no link continua o combinado de 3 px.
.marca-disco {
fill: currentColor;
transform-origin: 60px 60px;
}
@media (prefers-reduced-motion: no-preference) {
.brand:hover .marca-disco,
.brand:focus-visible .marca-disco {
transform: rotate(-8deg);
}
}
transform-origin em px fala o sistema do viewBox, não da tela. Centro do círculo em 60 60. Copie. Mude o grau. Preveja a inclinação. Recarregue. Ative reduzir movimento: a rotação some, a cor do currentColor permanece.
Não use SMIL (<animate>) neste volume. CSS na folha da página basta e respeita a mesma media query das outras animações.
img src="marca.svg" continua válido para a marca no cabeçalho quando você não precisa de currentColor. O alt descreve. Inline entra quando o hover do link e o disco precisam pintar juntos.
Copie o SVG para um arquivo .svg e ligue com img. Preveja disco sempre azul, mesmo no hover do texto ao lado. Recarregue. Volte ao inline para recuperar currentColor.
Um svg inline sem width e height pode estourar a coluna. Declare os dois ou controle no CSS com .marca { width: 3rem; height: auto; }. O viewBox cuida da proporção.
Atividades
- O que os quatro números de
viewBox="0 0 120 120"significam? - Por que
currentColornão pinta um SVG ligado só comimg? - Qual par torna um SVG inline a marca nomeada da página?
- Foto da Praia do Jacaré deve ser SVG? Por quê?
- O que acontece se dois
titleinline compartilham o mesmoid? - Por que
transform-origin: 60px 60pxfaz sentido no disco da marca?
Respostas comentadas
- Origem x, origem y, largura e altura do sistema interno de coordenadas. Não são pixels da tela.
- O arquivo em
imgnão entrega as formas à folha da página.fillnomain.cssnão alcança o disco. role="img"e<title>(comaria-labelledbynosvg).- Não. Fotografia é raster. SVG é para traço e forma.
- HTML inválido. O rótulo acessível aponta para o primeiro id e o segundo fica mudo ou errado.
- O centro do círculo no
viewBoxé 60, 60. A rotação gira em torno do disco, não do canto da página.
Referências
O arquivo completo
Referência do exemplo 35-svg, reproduzida aqui para que você possa conferir sem sair da página.
assets/javascript/simulacao.js
const form=document.querySelector("#simulacao");if(form){form.querySelector("button[type=submit]").disabled=false;form.addEventListener("submit",event=>{event.preventDefault();document.querySelector("#retorno").textContent="Simulação concluída. Nada foi enviado ou guardado.";});}