Como mudar a cor de um elemento svg?


346

Eu quero usar essa técnica http://css-tricks.com/svg-fallbacks/ e alterar a cor svg, mas até agora não consegui fazer isso. Coloquei isso no CSS, mas minha imagem é sempre preta, não importa o quê. Meu código:

.change-my-color {
  fill: green;
}
<svg>
    <image class="change-my-color" xlink:href="https://svgur.com/i/AFM.svg" width="96" height="96" src="ppngfallback.png" />
</svg>


Não sou especialista em svg, mas você já tentou alterar o preenchimento para a cor de fundo?
780 Meg em

@Megan em svg background-color é especificado com a propriedade 'fill' e a borda com 'stroke' (como você faria no Illustrator). w3.org/TR/SVG/propidx.html
Barbara

4
CSS do seu documento HTML não se aplicam a elementos SVG dentro <img />
Pawel

11
Isso é possível agora. Resposta simples e funcional aqui: stackoverflow.com/a/53336754/467240
mtyson 12/01

Respostas:


188

Você não pode alterar a cor de uma imagem dessa maneira. Se você carregar o SVG como uma imagem, não poderá alterar a forma como ela é exibida usando CSS ou Javascript no navegador.

Se você quer mudar sua imagem SVG, você tem que carregá-lo usando <object>, <iframe>ou usando <svg>embutido.

Se você quiser usar as técnicas da página, precisará da biblioteca Modernizr, onde poderá verificar o suporte ao SVG e exibir condicionalmente ou não uma imagem de fallback. Em seguida, você pode alinhar seu SVG e aplicar os estilos necessários.

Vejo :

Você pode alinhar seu SVG, marcar sua imagem de fallback com um nome de classe ( my-svg-alternate):

<svg width="96px" height="96px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
<path id="time-3-icon" .../>
</svg>

<image class="my-svg-alternate" width="96" height="96" src="ppngfallback.png" />

E no CSS, use a no-svgclasse Modernizr (CDN: http://ajax.aspnetcdn.com/ajax/modernizr/modernizr-2.7.2.js ) para verificar o suporte ao SVG. Se não houver suporte a SVG, o bloco SVG será ignorado e a imagem será exibida; caso contrário, a imagem será removida da árvore DOM ( display: none):

.my-svg-alternate {
  display: none;
}
.no-svg .my-svg-alternate {
  display: block;
  width: 100px;
  height: 100px;
  background-image: url(image.png);
}

Em seguida, você pode alterar a cor do seu elemento embutido:

#time-3-icon {
   fill: green;
}

5
Você não pode estilizar objectSVGs incorporados no documento de hospedagem.
18726 Javier Rey

11
@JavierRey, você pode injetar o estilo no conteúdo da tag do objeto via javascript. Mas você está certo de que ele não se aplica se você o adicionar à folha de estilo do documento de hospedagem.
Robert Longson

2
Estou usando a solução da @ manish-menaria e funciona perfeitamente.
Ryan Ellis

11
A resposta aceita deve ser alterada para: stackoverflow.com/a/53336754/467240
mtyson 12/01

374

Resposta 2020

O filtro CSS funciona em todos os navegadores atuais

Para alterar qualquer cor de SVGs

  1. Adicione a imagem SVG usando uma <img>tag.
<img src="dotted-arrow.svg" class="filter-green"/>
  1. Para filtrar para uma cor específica, use o seguinte Codepen (Clique aqui para abrir o codepen) para converter um código de cor hexadecimal em um filtro CSS:

Por exemplo, a saída para #00EE00é

filter: invert(42%) sepia(93%) saturate(1352%) hue-rotate(87deg) brightness(119%) contrast(119%);
  1. Adicione o CSS filtera esta classe.
    .filter-green{
        filter: invert(48%) sepia(79%) saturate(2476%) hue-rotate(86deg) brightness(118%) contrast(119%);
    }

5
Isso vem com a ressalva de costume sobre não ser suportado em versões mais antigas do navegador: developer.mozilla.org/en-US/docs/Web/CSS/...
Kevin Wang

17
Conforme observado no CodePen, se o seu SVG não for preto (o meu era cinza), adicionar brightness(0) saturate(100%)ao início da lista de filtros primeiro o tornará 100% preto, o que permite que os outros filtros o alterem para a cor correta.
Jdunning # 11/19

2
Além disso, muitos antecedentes fascinantes sobre a solução nesta questão do StackOverflow que informaram o CodePen.
Jdunning # 11/19

3
Meu cara. O suporte parece aceitável caniuse.com/#feat=css-filters .
Sam Doidge

funciona tão bem, usei esse codepen não afiliado para obter meu hex em um filtro: codepen.io/sosuke/pen/Pjoqqp
WEBjuju

220

Para alterar a cor de qualquer SVG, você pode alterar diretamente o código svg, abrindo o arquivo svg em qualquer editor de texto . O código pode se parecer com o código abaixo

<?xml version="1.0" encoding="utf-8"?>
    <!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
         width="500px" height="500px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">
    <g>
        <path d="M114.26,436.584L99.023,483h301.953l-15.237-46.416H114.26z M161.629,474.404h-49.592l9.594-29.225h69.223
            C181.113,454.921,171.371,464.663,161.629,474.404z"/>
    /*Some more code goes on*/
    </g>
    </svg>

Você pode observar que há algumas tags XML como caminho, círculo, polígono etc . Lá você pode adicionar sua própria cor com a ajuda do atributo style . Veja o exemplo abaixo

<path style="fill:#AB7C94;" d="M114.26,436.584L99.023,483h301.953l-15.237-46.416H114.26z M161.629,474.404h-49.592l9.594-29.225h69.223
                C181.113,454.921,171.371,464.663,161.629,474.404z"/>

Adicione o atributo style a todas as tags para obter o SVG da cor necessária


48
Por que não usar apenas atributos fillcomo este fill = "#AB7C94":? Não sei por que o styleatributo é necessário
bg17aw

4
Oi Daniel, sim, funciona. Eu não sabia que o preenchimento pode ser usado como um atributo. Desculpe por não perceber o seu comentário tão longo @ bg17aw
sushant047

30

Adicionada uma página de teste - para colorir SVG através das configurações de filtro:

POR EXEMPLO filter: invert(0.5) sepia(1) saturate(5) hue-rotate(175deg)

Carregar e colorir seu SVG - Jsfiddle

A ideia foi tirada de: https://blog.union.io/code/2017/08/10/img-svg-fill/


11
Obrigado, você acabou de me salvar de mim mesma. .custom-disabled > svg {filter:invert(0.2) sepia(1) saturte(0) hue-rotate(0);}fez exatamente o trabalho necessário para desativar o ícone.
roger

19

Somente SVG com informações de caminho . você não pode fazer isso com a imagem. Como o caminho, você pode alterar o traçado e preencher as informações e pronto. como Illustrator

assim: via CSS, você pode sobrescrever o fillvalor do caminho

path { fill: orange; }

mas se você deseja uma maneira mais flexível, como deseja alterá-lo com um texto ao ter algum efeito flutuante, use

path { fill: currentcolor; }

body {
  background: #ddd;
  text-align: center;
  padding-top: 2em;
}

.parent {
  width: 320px;
  height: 50px;
  display: block;
  transition: all 0.3s;
  cursor: pointer;
  padding: 12px;
  box-sizing: border-box;
}

/***  desired colors for children  ***/
.parent{
  color: #000;
  background: #def;
}
.parent:hover{
  color: #fff;
  background: #85c1fc;
}

.parent span{
  font-size: 18px;
  margin-right: 8px;
  font-weight: bold;
  font-family: 'Helvetica';
  line-height: 26px;
  vertical-align: top;
}
.parent svg{
  max-height: 26px;
  width: auto;
  display: inline;
}

/****  magic trick  *****/
.parent svg path{
  fill: currentcolor;
}
<div class='parent'>
  <span>TEXT WITH SVG</span>
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128" viewBox="0 0 32 32">
<path d="M30.148 5.588c-2.934-3.42-7.288-5.588-12.148-5.588-8.837 0-16 7.163-16 16s7.163 16 16 16c4.86 0 9.213-2.167 12.148-5.588l-10.148-10.412 10.148-10.412zM22 3.769c1.232 0 2.231 0.999 2.231 2.231s-0.999 2.231-2.231 2.231-2.231-0.999-2.231-2.231c0-1.232 0.999-2.231 2.231-2.231z"></path>
</svg>
</div>


12

a maneira mais fácil seria criar uma fonte a partir do SVG usando um serviço como https://icomoon.io/app/#/select ou algo semelhante. faça o upload do seu SVG, clique em "gerar fonte", inclua arquivos de fonte e css ao seu lado e use e estilize-o como qualquer outro texto. Eu sempre uso assim porque facilita muito o estilo.

EDIT: Como mencionado no artigo comentado pelas fontes de ícone do @ CodeMouse92, atrapalham os leitores de tela (e possivelmente são ruins para o SEO). Então, fique com os SVGs.


4
Também atrapalha os leitores de tela. Veja "Death to Icon Fonts" por Seren Davies
CodeMouse92 31/03

6

Você pode alterar a coloração SVG com css se usar alguns truques. Eu escrevi um pequeno roteiro para isso.

  • percorra uma lista de elementos que possuem uma imagem svg
  • carrega o arquivo svg como xml
  • buscar apenas parte svg
  • mudar a cor do caminho
  • substitua src pelo svg modificado como imagem embutida
$('img.svg-changeable').each(function () {
  var $e = $(this);
  var imgURL = $e.prop('src');

  $.get(imgURL, function (data) {
    // Get the SVG tag, ignore the rest
    var $svg = $(data).find('svg');

    // change the color
    $svg.find('path').attr('fill', '#000');

    $e.prop('src', "data:image/svg+xml;base64," + window.btoa($svg.prop('outerHTML')));
  });

});

o código acima pode não estar funcionando corretamente, eu implementei isso para elementos com uma imagem de fundo svg que funciona quase de maneira semelhante a isso. De qualquer forma, você precisa modificar esse script para se adequar ao seu caso. espero que tenha ajudado.


A propósito: Se você é um desenvolvedor de RoR, pode adicionar um novo método para o pré-compilador sass, que também pode fazer o trabalho. Isso é muito melhor porque você terá a imagem colorida correta codificada em base64 no seu arquivo css compilado. JS não é mais necessário! Talvez eu possa fornecer o código que escrevi, ter que falar com o CTO.
cydoc 17/07/2015

2
+1 por fornecer uma solução, em vez de dizer que não pode ser feito. Esta resposta também é relevante: stackoverflow.com/questions/11978995/… #
claytronicon

6

A máscara SVG em um elemento de caixa com uma cor de fundo resultará:

.icon{
  --size     : 70px;
  display    : inline-block;
  width      : var(--size);
  height     : var(--size);
  transition : .12s;
  -webkit-mask-size: cover;
  mask-size  : cover;
}

.icon-bike{
  background: black;
  -webkit-mask-image: url(https://image.flaticon.com/icons/svg/89/89139.svg);
  mask-image: url(hhttps://image.flaticon.com/icons/svg/89/89139.svg);
  animation: 1s frames infinite ease;
}

@keyframes frames {
  50% { background:red;  }
}
<i class="icon icon-bike" style="--size:150px"></i>


Nota - As máscaras SVG não são suportadas nos navegadores Internet Explorer


5

Alveje o caminho dentro do svg:

<svg>
   <path>....
</svg>

Você pode fazer inline, como:

<path fill="#ccc">

Ou

svg{
   path{
        fill: #ccc


2

Se você quiser fazer isso com um svg embutido, que é, por exemplo, uma imagem de plano de fundo em seu css:

background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='rgba(31,159,215,1)' viewBox='...'/%3E%3C/svg%3E");

é claro, substitua o ... pelo seu código de imagem embutido


2

Por exemplo, no seu HTML:

<body>
  <svg viewBox="" width="" height="">
    <path id="struct1" fill="#xxxxxx" d="M203.3,71.6c-.........."></path>
  </svg>
</body>

Use jQuery:

$("#struct1").css("fill","<desired colour>");

Isso só funciona se você incluir o arquivo SVG embutido no HTML. Editei sua resposta para deixar isso claro.
Flimm

0

Na verdade, existe uma solução muito mais flexível para esse problema: escrever um componente da Web que corrigirá o SVG como texto em tempo de execução. Também publicado em gist com um link para JSFiddle

👍 filtro: inverter (42%) sépia (93%) saturar (1352%) matiz-girar (87deg) brilho (119%) contraste (119%);

<html>

<head>
  <title>SVG with color</title>
</head>

<body>
  <script>
    (function () {
      const createSvg = (color = '#ff9933') => `
          <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="76px" height="22px" viewBox="-0.5 -0.5 76 22">
            <defs/>
              <g>
                <ellipse cx="5" cy="10" rx="5" ry="5" fill="#ff9933" stroke="none" pointer-events="all"/>
                <ellipse cx="70" cy="10" rx="5" ry="5" fill="#ff9933" stroke="none" pointer-events="all"/>
                <path d="M 9.47 12.24 L 17.24 16.12 Q 25 20 30 13 L 32.5 9.5 Q 35 6 40 9 L 42.5 10.5 Q 45 12 50 6 L 52.5 3 Q 55 0 60.73 3.23 L 66.46 6.46" fill="none" stroke="#ff9933" stroke-miterlimit="10" pointer-events="stroke"/>
              </g>
          </svg>`.split('#ff9933').join(color);

      function SvgWithColor() {
        const div = Reflect.construct(HTMLElement, [], SvgWithColor);
        const color = div.hasAttribute('color') ? div.getAttribute('color') : 'cyan';
        div.innerHTML = createSvg(color);
        return div;
      }

      SvgWithColor.prototype = Object.create(HTMLElement.prototype);
      customElements.define('svg-with-color', SvgWithColor);

      document.body.innerHTML += `<svg-with-color
        color='magenta' 
      ></svg-with-color>`;

    })();

  </script>
</body>

</html>

-1

maneira mais curta compatível com Bootstrap, sem JavaScript:

.cameraicon {
height: 1.6em;/* set your own icon size */
mask: url(/camera.svg); /* path to your image */
-webkit-mask: url(/camera.svg) no-repeat center;
}

e use-o como:

<td class="text-center">
    <div class="bg-secondary cameraicon"/><!-- "bg-secondary" sets actual color of your icon -->
</td>

-1

Abra sua imagem usando um navegador, clique com o botão direito do mouse na imagem, clique na fonte da página de exibição e você verá a tag svg da imagem. Copie e cole em seu html e altere o preenchimento para a cor de sua escolha


A resposta aceita já sugere reclinar e definir a cor como a solução.
Robert Longson

-1

Basta adicionar fill: "selectedColor" na tag svg da imagem: exemplo:

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#bbb9c6">
<path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"/><path d="M0 0h24v24H0z" fill="none"/></svg>

Essa é basicamente a mesma sugestão que esta resposta ou esta
Robert Longson

essas respostas mencionaram preencher a tag path, funcionou para mim na tag svg, por isso eu a
publiquei
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.