, e consultas de mídia CSS.Escrevi bastante recentemente sobre como preparo e otimizo código SVG para usar como gráficos estáticos ou em animações. Adoro trabalhar com SVG, mas sempre houve algo neles que me incomoda.
Para ilustrar como construo SVGs adaptativos, selecionei um episódio de O programa Quick Draw McGraw chamado “Bow Wow Bandit”, transmitido pela primeira vez em 1959.
Nele, Quick Draw McGraw convoca seu cão de caça Snuffles para resgatar seu companheiro Baba Looey. Como a maioria dos cartões de título da Hanna-Barbera do período, a arte foi feita por Lawrence (Art) Goble.
Digamos que eu projetei uma cena SVG como aquela baseada em Bow Wow Bandit, que tem uma proporção de 16:9 com uma viewBox tamanho de 1920×1080. Este SVG aumenta e diminui (a pista está no nome), então parece nítido quando é gigantesco e quando é minúsculo.
Mas em telas pequenas, a proporção de 16:9 (demonstração ao vivo) pode não ser o melhor formato e a imagem perde seu impacto. Às vezes, uma orientação retrato, como 3:4, seria melhor adequada ao tamanho da tela.
Mas é aí que reside o problema, pois não é fácil reposicionar elementos internos para diferentes tamanhos de tela usando apenas viewBox. Isso ocorre porque no SVG, as posições dos elementos internos são bloqueadas no sistema de coordenadas do original viewBoxentão você não pode alterar facilmente o layout entre, digamos, desktop e celular. Isso é um problema porque as animações e a interatividade geralmente dependem das posições dos elementos, que quebram quando o viewBox mudanças.
Meu desafio era servir uma versão 1080×1440 do Bow Wow Bandit para telas menores e uma versão diferente para telas maiores. Eu queria que a posição e o tamanho dos elementos internos – como Quick Draw McGraw e seu dawg Snuffles – mudassem para melhor se adequar a esses dois layouts. Para resolver isso, experimentei várias alternativas.
Observação: Por que não estamos apenas usando o com SVGs externos? O O elemento é brilhante para imagens responsivas, mas só funciona com formatos raster (como JPEG ou WebP) e arquivos SVG externos tratados como imagens. Isso significa que você não pode animar ou estilizar elementos internos usando CSS.
Mostrando e ocultando SVG
A escolha mais óbvia foi incluir dois SVGs diferentes em minha marcação, um para telas pequenas e outro para telas maiores, e então mostrá-los ou ocultá-los usando CSS e Media Queries:
#svg-small { display: block; }
#svg-large { display: none; }
@media (min-width: 64rem) {
#svg-small { display: none; }
#svg-mobile { display: block; }
}
Mas usando esse método, ambas as versões SVG são carregadas, o que, quando os gráficos são complexos, significa baixar muitos e muitos códigos desnecessários.
Substituindo SVGs usando JavaScript
Pensei em usar JavaScript para trocar o SVG maior em um ponto de interrupção especificado:
if (window.matchMedia('(min-width: 64rem)').matches) {
svgContainer.innerHTML = desktopSVG;
} else {
svgContainer.innerHTML = mobileSVG;
}
Deixando de lado o fato de que o JavaScript agora seria crítico para a forma como o design é exibido, ambos os SVGs normalmente seriam carregados de qualquer maneira, o que adiciona complexidade ao DOM e peso desnecessário. Além disso, a manutenção se torna um problema, pois agora existem duas versões da arte para manter, dobrando o tempo que levaria para atualizar algo tão pequeno quanto o formato da cauda do Quick Draw.
A solução: uma biblioteca de símbolos SVG e vários usos
Lembre-se, meu objetivo é:
- Sirva uma versão do Bow Wow Bandit em telas menores,
- Sirva uma versão diferente para telas maiores,
- Definir minha arte apenas uma vez (DRY) e
- Ser capaz de redimensionar e reposicionar elementos.
Eu não leio o suficiente sobre isso, mas o element permite definir elementos SVG reutilizáveis que podem ser ocultos e reutilizados para melhorar a capacidade de manutenção e reduzir o inchaço do código. Eles são como componentes para SVG: crie uma vez e use onde precisar:
UM é como armazenar um personagem em uma biblioteca. Posso referenciá-lo quantas vezes precisar para manter meu código consistente e leve. Usando elementos, posso inserir o mesmo símbolo várias vezes, em posições ou tamanhos diferentes e até mesmo em SVGs diferentes.
Cada deve ter o seu próprio viewBoxque define seu sistema de coordenadas interno. Isso significa prestar atenção especial em como os elementos SVG são exportados de aplicativos como o Sketch.
Exportando para viewboxes individuais
Escrevi antes sobre como exporto elementos em camadas para facilitar o trabalho com eles. Esse processo é um pouco diferente na criação de símbolos.
Normalmente, eu exportaria todos os meus elementos usando o mesmo viewBoxtamanho. Mas quando estou criando um symbolpreciso que ele tenha seu próprio específico viewBox.
Portanto, exporto cada elemento como um SVG de tamanho individual, o que me dá as dimensões necessárias para converter seu conteúdo em um arquivo SVG. symbol. Vamos pegar o SVG do chapéu do Quick Draw McGraw, que tem um viewBox tamanho de 294×182:
Eu troco as tags SVG por e adicione sua arte à minha biblioteca SVG:
Em seguida, repito o processo para todos os elementos restantes da minha arte. Agora, se eu precisar atualizar algum dos meus símbolos, as alterações serão aplicadas automaticamente a cada instância usada.
Usando um Em vários SVGs
Eu queria que meus elementos aparecessem em ambas as versões de Bow Wow Bandit, um arranjo para telas menores e um arranjo alternativo para telas maiores. Então, eu crio os dois SVGs:
…e insira links para meus símbolos em ambos:
Símbolos de posicionamento
Depois de colocar símbolos em meu layout usando meu próximo passo é posicioná-los, o que é especialmente importante se eu quiser layouts alternativos para diferentes tamanhos de tela. Os símbolos se comportam como grupos, para que eu possa dimensioná-los e movê-los usando atributos como width, heighte transform:
Posso colocar cada elemento de forma independente usando transform. Isso é poderoso porque, em vez de reposicionar elementos dentro dos meus SVGs, movo o referências. Meu layout interno permanece limpo e o tamanho do arquivo permanece pequeno porque não estou duplicando a arte. Um navegador carrega apenas uma vez, o que reduz a largura de banda e acelera a renderização da página. E porque estou sempre fazendo referência ao mesmo symbolsua aparência permanece consistente, independentemente do tamanho da tela.
Animando Elementos
Foi aqui que as coisas ficaram complicadas. Eu queria animar partes dos meus personagens – como o chapéu do Quick Draw se inclinando e suas pernas chutando. Mas quando adicionei animações CSS direcionadas a elementos internos dentro de um nada aconteceu.
Dica: Você pode animar o elemento em si, mas não elementos dentro do . Se você quiser que partes individuais se movam, crie seus próprios símbolos e anime cada uma delas. .
Acontece que você não pode estilizar ou animar um porque cria clones shadow DOM que não são facilmente segmentáveis. Então, eu tive que ser sorrateiro. Dentro de cada na minha biblioteca SVG, adicionei um elemento em torno da parte que eu queria animar:
…e animou-o usando um seletor de substring de atributo, visando o href atributo do use elemento:
use[href="#quick-draw-hat"] {
animation-delay: 0.5s;
animation-direction: alternate;
animation-duration: 1s;
animation-iteration-count: infinite;
animation-name: hat-rock;
animation-timing-function: ease-in-out;
transform-origin: center bottom;
}
@keyframes hat-rock {
from { transform: rotate(-2deg); }
to { transform: rotate(2deg); } }
Depois de criar meus dois SVGs visíveis — um para telas pequenas e outro para telas maiores — a etapa final é decidir qual versão mostrar em qual tamanho de tela. Eu uso CSS Media Queries para ocultar um SVG e mostrar o outro. Começo mostrando o SVG de tela pequena por padrão:
.svg-small { display: block; }
.svg-large { display: none; }
Então eu uso um min-width consulta de mídia para mudar para o SVG de tela grande em 64rem e acima:
@media (min-width: 64rem) {
.svg-small { display: none; }
.svg-large { display: block; }
}
Isso garante que haja apenas um SVG visível por vez, mantendo meu layout simples e o DOM livre de confusão desnecessária. E porque ambos os SVGs visíveis fazem referência ao mesmo oculto biblioteca, o navegador baixa a arte apenas uma vez, independentemente de quantas elementos aparecem nos dois layouts.
Concluindo
Ao combinar , consultas de mídia CSS e transformações específicas, posso criar SVGs adaptativos que reposicionam seus elementos sem duplicar conteúdo, carregar recursos extras ou depender de JavaScript. Preciso definir cada gráfico apenas uma vez em uma biblioteca de símbolos ocultos. Então posso reutilizar esses gráficos, conforme necessário, dentro de vários SVGs visíveis. Com o CSS fazendo a troca de layout, o o resultado é rápido e flexível.
É um lembrete de que algumas das técnicas mais poderosas da web não precisam de grandes estruturas ou ferramentas complexas — apenas um pouco de conhecimento sobre SVG e um uso inteligente do básico.

