Pular para o conteúdo
murad.guide

A Web Aberta

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

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.

Resumo dos conceitos: svg, viewBox, currentColor

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.

Resumo dos conceitos: currentColor, viewBox, svg

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

  1. O que os quatro números de viewBox="0 0 120 120" significam?
  2. Por que currentColor não pinta um SVG ligado só com img?
  3. Qual par torna um SVG inline a marca nomeada da página?
  4. Foto da Praia do Jacaré deve ser SVG? Por quê?
  5. O que acontece se dois title inline compartilham o mesmo id?
  6. Por que transform-origin: 60px 60px faz sentido no disco da marca?

Respostas comentadas

  1. Origem x, origem y, largura e altura do sistema interno de coordenadas. Não são pixels da tela.
  2. O arquivo em img não entrega as formas à folha da página. fill no main.css não alcança o disco.
  3. role="img" e <title> (com aria-labelledby no svg).
  4. Não. Fotografia é raster. SVG é para traço e forma.
  5. HTML inválido. O rótulo acessível aponta para o primeiro id e o segundo fica mudo ou errado.
  6. 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.";});}