Voltar

Converter tags de imagem com arquivos SVG em tags SVG inline

Se você sente a necessidade de transformar um SVG que está sendo usado via tag de imagem em um SVG inline, para personalizar ele a teu gosto via CSS, vou te ensinar um método muito prático para realizar isso.

Como eu cheguei nessa necessidade

Tinha uma página que funcionava como template, então o que mudava além do conteúdo era a cor de alguns textos, bordas, background e também ícones SVGs que vinham em tags de imagem. Como eu precisava fazer com que os ícone acompanhassem o tema, o modo como eles eram chamados não me permitia fazer isso.

Exemplo:

<img src="assets/images/calendario.svg" class="card-icon" id="calendario">

Daí em meio as minhas pesquisas eu encontrei o seguinte código JS que realiza o que preciso:

const convertImages = (query, callback) => {
	const images = document.querySelectorAll(query);

	images.forEach(image => {
		fetch(image.src)
		.then(res => res.text())
		.then(data => {
			const parser = new DOMParser();
			const svg = parser.parseFromString(data, 'image/svg+xml').querySelector('svg');

			if (image.id) svg.id = image.id;
			if (image.className) svg.classList = image.classList;

			image.parentNode.replaceChild(svg, image);
		})
		.then(callback)
		.catch(error => console.error(error))
	});
}

O autor explica:

É uma função bastante simples que recebe uma consulta e um retorno de chamada como argumentos. Tudo o que você precisa fazer é chamar essa função com uma consulta pelas imagens que deseja converter e ela percorrerá cada uma delas Buscará o SVG e usará o DOMParser para extrair os dados SVG do arquivo. Depois disso ele copia os atributos id e class da imagem para a variável SVG e substitui a imagem pelos dados SVG.

Simples de entender, né? Além disso da para copiar mais propriedade se quiser, basta editar o código a seu gosto.

Uma sugestão minha

Quando usei pela primeira vez eu achei feio que enquanto o site carrega eu fico vendo a imagem lá e só depois é que ele converte. Então eu sugiro usar da seguinte forma:

Na imagem você coloca a URL sendo uma data, ficando data-src="URL", assim:

<img data-src="assets/images/calendario.svg" class="card-icon" id="calendario">

Depois mudamos onde tem fetch(image.src) (a linha 5) para fetch(image.dataset.src), ficando assim:

const convertImages = (query, callback) => {
	const images = document.querySelectorAll(query);

	images.forEach(image => {
		fetch(image.dataset.src)
		.then(res => res.text())
		.then(data => {
			const parser = new DOMParser();
			const svg = parser.parseFromString(data, 'image/svg+xml').querySelector('svg');

			if (image.id) svg.id = image.id;
			if (image.className) svg.classList = image.classList;

			image.parentNode.replaceChild(svg, image);
		})
		.then(callback)
		.catch(error => console.error(error))
	});
}

Pronto! Você só verá o SVG quando o JS for executado.

Uma última coisa

Eu li comentários de pessoas que usaram esse código e relataram erro de CORS. Isso vai depende da fonte de onde vem a imagem. Eu puxei de uma API, então não enfrentei esse problema. Se alguém passar por isso e tiver uma solução é só me falar que eu atualizo aqui.

Fonte desse tutorial: https://dev.to/luisaugusto/how-to-convert-image-tags-with-svg-files-into-inline-svg-tags-3jfl