img src SVG alterando os estilos com CSS

374

html

<img src="logo.svg" alt="Logo" class="logo-img">

css

.logo-img path {
  fill: #000;
}

O svg acima carrega e é nativo, fill: #fffmas quando eu uso o acima csspara tentar mudá-lo para preto, ele não muda, é a primeira vez que eu jogo com SVG e não sei ao certo por que ele não está funcionando.

ngplayground
fonte
25
Você não pode afetar SVG imagens assim ... apenas elementos SVG em linha
Paulie_D
Verifique minha resposta aqui para usar o conteúdo de SVG e CSS. stackoverflow.com/questions/11978995/…
Benjamin

Respostas:

153

Se seu objetivo é apenas alterar a cor do logotipo e você não necessariamente precisar usar CSS, não use javascript ou jquery, conforme sugerido por algumas respostas anteriores.

Para responder com precisão à pergunta original, basta:

  1. Abra o seu logo.svgem um editor de texto.

  2. procure fill: #fffe substitua-o porfill: #000

Por exemplo, você logo.svgpode ficar assim quando aberto em um editor de texto:

<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
  <path d="M0 0h24v24H0z" fill="none"/>
  <path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" fill="#fff"/>
</svg>

... basta alterar o preenchimento e salvar.

Rowe Morehouse
fonte
6
... e se não houver "preenchimento", basta adicioná-lo aos itens pathou circlecomo <path fill="#777777" d="m129.774,74.409c-5.523,....
SaeX
11
e se meu logotipo tiver uma cor no cabeçalho e outra no rodapé?
rubens.lopes
. @ ruben.lopes dois arquivos diferentes, ou dois inlines diferentes seria mais simples
Rowe Morehouse
11
você pode usar também o fill="currentColor"então usar a colorno elemento pai css-tricks.com/cascading-svg-fill-color
Serge
10
Obviamente, isso é possível e não é realmente uma resposta útil.
Timmmm
101

Você pode definir seu SVG como uma máscara. Dessa forma, definir uma cor de fundo atuaria como sua cor de preenchimento.

HTML

<div class="logo"></div>

CSS

.logo {
    background-color: red;
    -webkit-mask: url(logo.svg) no-repeat center;
    mask: url(logo.svg) no-repeat center;
}

JSFiddle: https://jsfiddle.net/KuhlTime/2j8exgcb/
MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/mask

Verifique se o seu navegador suporta este recurso: https://caniuse.com/#search=mask

André Kuhlmann
fonte
3
Portanto, para qualquer coisa, exceto o site interno, não pode ser usado.
Henrik Vendelbo
9
89% de suporte global em 29 de maio de 2016.
Gajus 29/05
11
Esta é uma solução incrível para situações como a descrita aqui , onde usar algo que não seja uris de dados em CSS é um pouco trabalhoso. Obrigado!
Gark Garcia
3
não está funcionando. diz que maské um invalid property value. Estou testando isso no chrome.
Eren555 28/01
11
@MadMac Estou executando a mesma versão do Chrome, mas não consegui replicar esse comportamento. É o JSFiddle que você tentou ou seu código?
André Kuhlmann
78

Tente CSS puro:

.logo-img {
  // to black
  filter: invert(1);
  // or to blue
  // filter: invert(1) sepia(1) saturate(5) hue-rotate(175deg);
}

mais informações neste artigo https://blog.union.io/code/2017/08/10/img-svg-fill/

Feri
fonte
Estava obtendo uma cor diferente no Edge do que em outros navegadores com uma das minhas tentativas recentemente.
Julix 08/03/19
4
Isso funciona no navegador mais, mas eu tive alguns problemas com o navegador IOS-Safari.
Simon Ludwig
30

2018: se você deseja uma cor dinâmica, não deseja usar javascript e não deseja um SVG embutido, use uma variável CSS. Funciona no Chrome, Firefox e Safari. editar: e Edge

<svg>
    <use xlink:href="logo.svg" style="--color_fill: #000;"></use>
</svg>

No seu SVG, substitua todas as instâncias de style="fill: #000"por style="fill: var(--color_fill)".

norte-americano
fonte
11
Qual é o suporte do navegador para isso
Kevin Goedecke
@KevinGoedecke Chrome, Firefox, Safari e Edge
NorthAmerican
4
Parece reprovado no SVG 2
vsync 8/18
5
@northamerican - links para outras respostas do stackoverflow como "provas" são irrelevantes. qualquer um pode escrever qualquer coisa nesta plataforma. MDN:"This feature has been removed from the Web standards. Though some browsers may still support it, it is in the process of being dropped"
vsync
8
Parece que xlink:hreffoi preterido em favor de href. Então, isso ainda pode funcionar.
Benjamin Intal
20

Você primeiro precisará injetar o SVG no DOM HTML.

Existe uma biblioteca de código aberto chamada SVGInject que faz isso por você. Ele usa o onloadatributo para disparar a injeção.

Aqui está um exemplo mínimo usando SVGInject:

<html>
  <head>
    <script src="svg-inject.min.js"></script>
  </head>
  <body>
    <img src="image.svg" onload="SVGInject(this)" />
  </body>
</html>

Após o carregamento da imagem onload="SVGInject(this), a injeção será acionada e o <img>elemento será substituído pelo conteúdo do arquivo SVG fornecido no srcatributo

Ele resolve vários problemas com a injeção de SVG:

  1. Os SVGs podem ficar ocultos até a injeção terminar. Isso é importante se um estilo já estiver aplicado durante o tempo de carregamento, o que causaria um breve "flash de conteúdo sem estilo".

  2. Os <img>elementos se injetam automaticamente. Se você adicionar SVGs dinamicamente, não precisará se preocupar em chamar a função de injeção novamente.

  3. Uma sequência aleatória é adicionada a cada ID no SVG para evitar ter o mesmo ID várias vezes no documento se um SVG for injetado mais de uma vez.

SVGInject é Javascript simples e funciona com todos os navegadores que suportam SVG.

Disclaimer: Eu sou o co-autor do SVGInject

Waruyama
fonte
3
Essa é a resposta mais direta. Eu testei no Chrome, Firefox e Edge e funciona perfeitamente.
Sébastien Lorion 26/06/19
15

A resposta do @Praveen é sólida.

Como não consegui responder no meu trabalho, criei uma função de jquery hover para ele.

CSS

.svg path {
   transition:0.3s all !important;
}

JS / JQuery

// code from above wrapped into a function
replaceSVG();

// hover function
// hover over an element, and find the SVG that you want to change
$('.element').hover(function() {
    var el = $(this);
    var svg = el.find('svg path');
    svg.attr('fill', '#CCC');
}, function() {
    var el = $(this);
    var svg = el.find('svg path');
    svg.attr('fill', '#3A3A3A');
});
Matt Wujek
fonte
11
isso não funcionaria apenas se o SVG estivesse em linha para começar?
Daniel Thompson
Sim - mas se você estiver trabalhando com muitos arquivos SVG ou os atualizando regularmente, é muito difícil administrá-los.
Matt Wujek
15

Por que não criar uma webfont com sua imagem ou imagens svg, importar a webfont no css e alterar a cor do glifo usando o atributo css color? Não é necessário javascript

gringo
fonte
5
Se o seu svg possui vários elementos de cores diferentes, esta solução se torna muito hacky (vários elementos interpostos).
kakaja
11
@kakaja Esta é uma solução apenas para imagens vetoriais com 1 cor. ver a resposta de bpulecio para mais detalhes
gringo
11
Porque ícone não é texto. As fontes são para texto. Svgs são para ícones.
Lazar Ljubenović
2
@ LazarLjubenović - tecnicamente, o texto é feito de caracteres que são símbolos e ícones também são símbolos, por isso, muitos não têm problemas ao usar fontes de ícone. é como criar "outra" linguagem textual. Mandarim usa "ícones" e não letras também, não é incomum na humanidade a ícones de uso como "texto"
vsync
11
Enquanto isso soa como uma solução interessante, eu realmente recomendo para elaborar a resposta em algo mais parecido com "como" em vez de "por que não"
YakovL
15

Esta resposta é baseada na resposta https://stackoverflow.com/a/24933495/3890888, mas com uma versão JavaScript simples do script usado lá.

Você precisa fazer com que o SVG seja um SVG embutido . Você pode fazer uso desse script, adicionando uma classe svgà imagem:

/*
 * Replace all SVG images with inline SVG
 */
document.querySelectorAll('img.svg').forEach(function(img){
    var imgID = img.id;
    var imgClass = img.className;
    var imgURL = img.src;

    fetch(imgURL).then(function(response) {
        return response.text();
    }).then(function(text){

        var parser = new DOMParser();
        var xmlDoc = parser.parseFromString(text, "text/xml");

        // Get the SVG tag, ignore the rest
        var svg = xmlDoc.getElementsByTagName('svg')[0];

        // Add replaced image's ID to the new SVG
        if(typeof imgID !== 'undefined') {
            svg.setAttribute('id', imgID);
        }
        // Add replaced image's classes to the new SVG
        if(typeof imgClass !== 'undefined') {
            svg.setAttribute('class', imgClass+' replaced-svg');
        }

        // Remove any invalid XML tags as per http://validator.w3.org
        svg.removeAttribute('xmlns:a');

        // Check if the viewport is set, if the viewport is not set the SVG wont't scale.
        if(!svg.getAttribute('viewBox') && svg.getAttribute('height') && svg.getAttribute('width')) {
            svg.setAttribute('viewBox', '0 0 ' + svg.getAttribute('height') + ' ' + svg.getAttribute('width'))
        }

        // Replace image with new SVG
        img.parentNode.replaceChild(svg, img);

    });

});

E então, agora se você fizer:

.logo-img path {
  fill: #000;
}

Ou talvez:

.logo-img path {
  background-color: #000;
}

JSFiddle: http://jsfiddle.net/erxu0dzz/1/

Seb3736
fonte
11
Ótimos trabalhos. além disso, se nossa página tiver vários svgs, precisaremos colocar o bloco de busca no IIFE.
Sandeep Sharma
11
Ótimo! Funciona bem com o ES6. Se você não se importa com o IE 9, pode usar: parser.parseFromString(text, "image/svg+xml");
ChristoKiwi 4/17/17
Não funciona no UIWebView no iOS 9.3.5. Eu acho que pode ser devido ao uso fetchque foi adicionado ao Safari na 10.1 ( developer.mozilla.org/en-US/docs/Web/API/Fetch_API ). A versão do jQuery acima funciona.
Maria-Ines Carrera
7

Use filtros para transformar em qualquer cor.

Encontrei recentemente esta solução e espero que alguém possa usá-la. Como a solução usa filtros, ela pode ser usada com qualquer tipo de imagem. Não é apenas svg.

Se você tiver uma imagem em uma única cor da qual deseja alterar a cor, poderá fazer isso com a ajuda de alguns filtros. Também funciona em imagens multicoloridas, mas você não pode segmentar uma cor específica. Somente a imagem inteira.

Os filtros vieram do script proposto em Como transformar preto em qualquer cor, usando apenas filtros CSS. Se você deseja mudar o branco para qualquer cor, pode ajustar o valor invertido em cada filtro.

.startAsBlack{
  display: inline-block;
  width: 50px;
  height: 50px;
  background: black;
}

.black-green{
  filter: invert(43%) sepia(96%) saturate(1237%) hue-rotate(88deg) brightness(128%) contrast(119%);
}

.black-red{
  filter: invert(37%) sepia(93%) saturate(7471%) hue-rotate(356deg) brightness(91%) contrast(135%);
}

.black-blue{
  filter: invert(12%) sepia(83%) saturate(5841%) hue-rotate(244deg) brightness(87%) contrast(153%);
}

.black-purple{
  filter: invert(18%) sepia(98%) saturate(2657%) hue-rotate(289deg) brightness(121%) contrast(140%);
}
Black to any color: <br/>
<div class="startAsBlack black-green"></div>
<div class="startAsBlack black-red"></div>
<div class="startAsBlack black-blue"></div>
<div class="startAsBlack black-purple"></div>

JasperZelf
fonte
4

Para expandir a resposta do @gringo, o método Javascript descrito em outras respostas funciona, mas exige que o usuário baixe arquivos de imagem desnecessários e, na IMO, ele incha seu código.

Eu acho que uma abordagem melhor seria migrar todos os gráficos vetoriais de uma cor para um arquivo webfont. Eu usei o Fort Awesome no passado e funciona muito bem para combinar seus ícones / imagens personalizados no formato SVG, juntamente com quaisquer ícones de terceiros que você possa estar usando (Font Awesome, ícones Bootstrap, etc.) em um único arquivo de fonte da Web o usuário precisa fazer o download. Você também pode personalizá-lo, para incluir apenas os ícones de terceiros que estiver usando. Isso reduz o número de solicitações que a página precisa fazer e o peso total da página, especialmente se você já estiver incluindo bibliotecas de ícones de terceiros.

Se você preferir uma opção mais orientada a desenvolvedores, poderia "npm svg webfont" no Google e usar um dos módulos de nó mais apropriados para o seu ambiente.

Uma vez que você tenha feito uma dessas duas opções, poderá alterar facilmente a cor via CSS e, muito provavelmente, acelerará o site no processo.

bpulecio
fonte
Você deve tentar sprites SVG. Na minha experiência, as fontes da web têm problemas aleatórios entre as versões do navegador. Tente isso: fontastic.me - mas use as versões SVG sprite - e veja o que você pensa. :)
sheriffderek
4

Se você estiver apenas alternando a imagem entre a cor real e o preto e branco, poderá definir um seletor como:

{filter: none;}

e outro como:

{filter:grayscale(100%);}
wcb1
fonte
3

Simples..

Você pode usar este código:

<svg class="logo">
  <use xlink:href="../../static/icons/logo.svg#Capa_1"></use>
</svg>

Primeiro especifique o caminho do svg e depois escreva seu ID, neste caso "Capa_1". Você pode obter o ID do svg abrindo-o em qualquer editor.

Em css:

.logo {
  fill: red;
}
Hamza Jamal
fonte
kabrice, Você pode usar este código codepen.io/hmzajmal/pen/ZEGvWYa
Hamza Jamal
2

O principal problema no seu caso é que você está importando o svg de uma <img>tag que oculta a estrutura SVG.

Você precisa usar a <svg>tag em conjunto com a <use>para obter o efeito desejado. Para fazê-lo funcionar, você precisa fornecer um idcaminho para o caminho que deseja usar no arquivo SVG <path id='myName'...>para poder recuperá-los da <use xlink:href="#myName"/>tag. Experimente o snippet abaixo.

Observe que você pode colocar qualquer URL antes do fragmento #se quiser carregar o SVG de uma fonte externa (e não incorporá-lo ao seu HTML). Além disso, geralmente você não especifica o preenchimento no CSS. É melhor considerar o uso fill:"currentColor"no próprio SVG. O valor da cor CSS do elemento correspondente será então usado no local.

Flavien Volken
fonte
2

Como o SVG é basicamente código, você precisa apenas de conteúdo. Eu usei o PHP para obter conteúdo, mas você pode usar o que quiser.

<?php
$content    = file_get_contents($pathToSVG);
?>

Em seguida, imprimi o conteúdo "como está" dentro de um contêiner div

<div class="fill-class"><?php echo $content;?></div>

Para definir finalmente uma regra para childs SVG do contêiner no CSS

.fill-class > svg { 
    fill: orange;
}

Eu obtive esses resultados com um ícone de material SVG:

Mozilla Firefox 59.0.2 (64 bits) Linux

insira a descrição da imagem aqui

Google Chrome66.0.3359.181 (Build oficial) (64 bits) Linux

insira a descrição da imagem aqui

Opera 53.0.2907.37 Linux

insira a descrição da imagem aqui

Benjamin
fonte
Não posso votar, mas, por favor, nunca faça isso.
Lixadeira19
5
Razões? Alternativas?
Benjamin
Meu motivo para não fazer isso é que isso impede que o navegador armazene em cache o SVG. A alternativa é usar um injetor SVG mencionado em algumas outras respostas aqui. O arquivo SVG ainda será armazenado em cache pelo navegador e o SVG injetado ainda pode ser estilizado com CSS. Mas eu não voto negativo em você.
Sần Trần-Nguyễn
Eu entendo, mas de qualquer maneira, o cache não é mencionado. A melhor resposta tem o código JavaScript que pode ser recarregado (ou não) todas as vezes pelo cabeçalho expirar a manipulação ou forçar um hash após o link do nome do arquivo.
227 Benjamin Benjamin
2

Isso pode ser útil para pessoas que usam PHPem combinação com.svg imagens que desejam manipular com CSS.

Você não pode sobrescrever propriedades dentro de uma tag img com CSS. Mas quando o código-fonte svg está incorporado no HTML, você certamente pode. Eu gosto de resolver esse problema com uma require_oncefunção na qual incluo um.svg.php arquivo. É como importar uma imagem, mas você ainda pode sobrescrever estilos com CSS!

Primeiro inclua o arquivo svg:

<?php require_once( '/assets/images/my-icon.svg.php' ); ?>

E inclui este ícone, por exemplo:

<svg xmlns="http://www.w3.org/2000/svg" width="20.666" height="59.084" viewBox="0 0 20.666 59.084"><g transform="translate(-639.749 -3139)"><path d="M648.536,3173.876c0-2.875-1.725-3.8-3.471-3.8-1.683,0-3.49.9-3.49,3.8,0,3,1.786,3.8,3.49,3.8C646.811,3177.676,648.536,3176.769,648.536,3173.876Zm-3.471,2.341c-.883,0-1.437-.513-1.437-2.341,0-1.971.615-2.381,1.437-2.381.862,0,1.438.349,1.438,2.381,0,1.907-.616,2.339-1.438,2.339Z" fill="#142312"/><path d="M653.471,3170.076a1.565,1.565,0,0,0-1.416.9l-6.558,13.888h1.2a1.565,1.565,0,0,0,1.416-.9l6.559-13.887Z" fill="#142312"/><path d="M655.107,3177.263c-1.684,0-3.471.9-3.471,3.8,0,3,1.766,3.8,3.471,3.8,1.745,0,3.49-.9,3.49-3.8C658.6,3178.186,656.851,3177.263,655.107,3177.263Zm0,6.139c-.884,0-1.438-.514-1.438-2.34,0-1.972.617-2.381,1.438-2.381.862,0,1.437.349,1.437,2.381,0,1.909-.616,2.34-1.437,2.34Z" fill="#142312"/><path d="M656.263,3159.023l-1.49-14.063a1.35,1.35,0,0,0,.329-.293,1.319,1.319,0,0,0,.268-1.123l-.753-3.49a1.328,1.328,0,0,0-1.306-1.054h-6.448a1.336,1.336,0,0,0-1.311,1.068l-.71,3.493a1.344,1.344,0,0,0,.276,1.112,1.532,1.532,0,0,0,.283.262l-1.489,14.087c-1.7,1.727-4.153,4.871-4.153,8.638v28.924a1.339,1.339,0,0,0,1.168,1.49,1.357,1.357,0,0,0,.17.01h17.981a1.366,1.366,0,0,0,1.337-1.366v-29.059C660.414,3163.893,657.963,3160.749,656.263,3159.023Zm-8.307-17.349h4.274l.176.815H647.79Zm9.785,43.634v10.1H642.434v-17.253a4.728,4.728,0,0,1-2.028-4.284,4.661,4.661,0,0,1,2.028-4.215v-2c0-3.162,2.581-5.986,3.687-7.059a1.356,1.356,0,0,0,.4-.819l1.542-14.614H652.1l1.545,14.618a1.362,1.362,0,0,0,.4.819c1.109,1.072,3.688,3.9,3.688,7.059v9.153a5.457,5.457,0,0,1,0,8.5Z" fill="#142312"/></g></svg>

Agora podemos alterar facilmente a cor do preenchimento desta forma com CSS:

svg path {
  fill: blue;
}

Eu tentei primeiro resolver esse problema, file_get_contents()mas a solução acima é muito mais rápida.

Floris
fonte
0

Saiba que essa é uma pergunta antiga, mas recentemente nos deparamos com o mesmo problema e resolvemos do lado do servidor. Esta é uma resposta específica ao php, mas tenho certeza de que outros envs têm algo semelhante. em vez de usar a tag img, você renderiza o svg como svg desde o início.

public static function print_svg($file){
    $iconfile = new \DOMDocument();
    $iconfile->load($file);
    $tag = $iconfile->saveHTML($iconfile->getElementsByTagName('svg')[0]);
    return $tag;
}

Agora, quando você renderizar o arquivo, você terá svg completo em linha

nechemya ungar
fonte
0

abra o ícone svg no seu editor de código e adicione uma classe após a tag path:

<path class'colorToChange' ...

Você pode adicionar classe ao svg e alterar a cor da seguinte maneira:

codepen

Hamza Jamal
fonte
-2

Se você tiver acesso ao JQuery, estendendo-se para a resposta de Praveen, é possível alterar programaticamente a cor de diferentes elementos aninhados dentro do SVG da seguinte forma:

$('svg').find('path, text').css('fill', '#ffffff');

Na localização, você pode mencionar diferentes elementos que precisam ser alterados em cores.

manyu
fonte