Como alterar a cor da imagem SVG usando CSS (substituição da imagem SVG jQuery)?

437

Esta é uma sessão de perguntas e respostas de um pedaço de código útil que eu criei.

Atualmente, não há uma maneira fácil de incorporar uma imagem SVG e, em seguida, ter acesso aos elementos SVG via CSS. Existem vários métodos de uso de estruturas JS SVG, mas eles são muito complicados se tudo o que você está fazendo é criar um ícone simples com um estado de rolagem.

Então, aqui está o que eu criei, que eu acho que é de longe a maneira mais fácil de usar arquivos SVG em um site. Ele leva o conceito dos métodos de substituição de texto para imagem, mas até onde sei, nunca foi feito para SVGs.

Esta é a questão:

Como incorporar um SVG e alterar sua cor no CSS sem usar uma estrutura JS-SVG?

Drew Baker
fonte
1
Infelizmente, a tag img não funciona com arquivos svg no IE, portanto, lembre-se disso. O IE reconhece tags incorporadas. Enfim, bom trabalho!
2
Para svg, você deve usar a propriedade css "fill". Para imagens, é apropriado usar "filtro". De fato, "Filtro" funciona para ambos, mas é desnecessário fazer todo esse trabalho para um gráfico vetorial.
Samy Bencherif

Respostas:

536

Primeiro, use uma tag IMG no seu HTML para incorporar um gráfico SVG. Eu usei o Adobe Illustrator para fazer o gráfico.

<img id="facebook-logo" class="svg social-link" src="/images/logo-facebook.svg"/>

É assim que você incorporaria uma imagem normal. Note que você precisa configurar o IMG para ter uma classe de svg. A classe 'social-link' é apenas um exemplo. O ID não é obrigatório, mas é útil.

Em seguida, use esse código jQuery (em um arquivo separado ou embutido no HEAD).

    /**
     * Replace all SVG images with inline SVG
     */
        jQuery('img.svg').each(function(){
            var $img = jQuery(this);
            var imgID = $img.attr('id');
            var imgClass = $img.attr('class');
            var imgURL = $img.attr('src');

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

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

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

                // Replace image with new SVG
                $img.replaceWith($svg);

            }, 'xml');

        });

O que o código acima faz é procurar todos os IMGs com a classe 'svg' e substituí-lo pelo SVG embutido do arquivo vinculado. A grande vantagem é que ele permite que você use CSS para alterar a cor do SVG agora, da seguinte forma:

svg:hover path {
    fill: red;
}

O código do jQuery que escrevi também transporta o ID e as classes das imagens originais. Portanto, este CSS também funciona:

#facebook-logo:hover path {
    fill: red;
}

Ou:

.social-link:hover path {
    fill: red;
}

Você pode ver um exemplo disso trabalhando aqui: http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html

Temos uma versão mais complicada que inclui armazenamento em cache aqui: https://github.com/funkhaus/style-guide/blob/master/template/js/site.js#L32-L90

Drew Baker
fonte
6
Por vezes, pode não funcionar em Safari (para, por exemplo), para garantir que os dados retornados é legível, remplace o });de US $ .get com}, 'xml');
Joan
29
Você provavelmente poderia até substituir o seletor img[src$=".svg"]e eliminar a necessidade da svgclasse.
Casey Chu
2
@ LeonGaban Acho que não há uma maneira de direcionar o preenchimento de uma imagem de fundo. Seria super útil se você pudesse!
Tirou Baker
3
Um pouco atrasado, @LeonGaban, mas uma maneira melhor de fazê-lo provavelmente seria remover completamente o atributo de preenchimento e confiar em um arquivo CSS para adicionar um preenchimento ao svg pai. $('#ico_company path').removeAttr('fill'). Então você poderia fazer #ico_company { fill: #ccc }em seu arquivo CSS
BioBall
2
@Saku, seria fácil fazer com que o jQuery definisse todos os caminhos como iguais à cor da fonte, fazendo algo como `var color = $ img.closest ('p'). Css ('color'); $ svg.find ('caminho'). attr ('preenchimento', cor); `Mas acho que este é um trabalho melhor para o CSS.
Tirou Baker
56

Estilo

svg path {
    fill: #000;
}

Roteiro

$(document).ready(function() {
    $('img[src$=".svg"]').each(function() {
        var $img = jQuery(this);
        var imgURL = $img.attr('src');
        var attributes = $img.prop("attributes");

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

            // Remove any invalid XML tags
            $svg = $svg.removeAttr('xmlns:a');

            // Loop through IMG attributes and apply on SVG
            $.each(attributes, function() {
                $svg.attr(this.name, this.value);
            });

            // Replace IMG with SVG
            $img.replaceWith($svg);
        }, 'xml');
    });
});
Henrik Albrechtsson
fonte
1
Se você não tem um atributo de largura, ele apenas cria um com um número errado. width="170.667"no meu caso
stallingOne
2
Isso não é perfeito, pois perde as dimensões img anteriores.
RichieHH
Olá, suponha que eu tenha svg diferente com cores differnet cada. Usando este método, todas as minhas cores svg se tornam as mesmas do primeiro svg que está sendo repetido. Alguma idéia de como eu posso lidar com isso para que cada cor permaneça a mesma de antes?
tnkh
1
note que se o seu svg é feito também de não- pathformas (como rect), você também precisará manipulá-los em css
Mugen
33

Agora você pode usar o filter propriedade CSS nos navegadores mais modernos (incluindo o Edge, mas não o IE11). Funciona em imagens SVG e em outros elementos. Você pode usar hue-rotateou invertmodificar cores, embora elas não permitam modificar cores diferentes independentemente. Eu uso a seguinte classe CSS para mostrar uma versão "desativada" de um ícone (onde o original é uma imagem SVG com cores saturadas):

.disabled {
    opacity: 0.4;
    filter: grayscale(100%);
    -webkit-filter: grayscale(100%);
}

Isso torna o cinza claro na maioria dos navegadores. No IE (e provavelmente no Opera Mini, que eu não testei), é visivelmente desbotado pela propriedade opacity, que ainda parece muito boa, embora não seja cinza.

Aqui está um exemplo com quatro classes CSS diferentes para o Twemoji ícone de campainha : original (amarelo), a classe "desativada" acima, hue-rotate(verde) e invert(azul).

aldel
fonte
Só notei que o invert é uma boa solução se você não deseja criar fontes de ícones. Eu usei esse código jQuery para ícone de mudança no cabeçalho do meu site de acordo com propriedade de cor css (aviso que estou usando ícones png brancos):if ($('.w3-top img').css("color") == "rgb(0, 0, 0)") { $('.w3-top img').css("filter", "invert(100%)"); $('.w3-top img').css("-webkit-filter", "invert(100%)"); };
RedClover
Ótima abordagem. Editei meu xml SVG para adicionar a cor do ícone de destino e usei uma classe .icon-disabled para acinzentá-la.
SushiGuy
Aviso que explora velhos não suporta filtro: w3schools.com/cssref/css3_pr_filter.asp
JillAndMe
25

Como alternativa, você pode usar CSS mask, o suporte concedido ao navegador não é bom, mas você pode usar um fallback

.frame {
    background: blue;
    -webkit-mask: url(image.svg) center / contain no-repeat;
}
seanjacob
fonte
14
MDN especifica que -webkit-masknão deve ser usado em nenhum site de produção.
vaindil
1
não pinta o svg #
1419
Talvez seja relevante dizer que agora, quatro anos depois, esta solução está funcionando em todos os principais navegadores. Acabei de testar aqui e está 100% ok.
Daniel Lemes
23

Se você pode incluir arquivos (o PHP inclui ou inclui pelo CMS de sua escolha) em sua página, você pode adicionar o código SVG e incluí-lo em sua página. Isso funciona da mesma maneira que colar a fonte SVG na página, mas torna a marcação da página mais limpa.

O benefício é que você pode segmentar partes do seu SVG via CSS para passar o mouse - não é necessário javascript.

http://codepen.io/chriscoyier/pen/evcBu

Você só precisa usar uma regra CSS como esta:

#pathidorclass:hover { fill: #303 !important; }

Observe que o !importantbit é necessário para substituir a cor de preenchimento.

trebor1979
fonte
3
Para aqueles que usam AngularJS:<div ng-include="'svg.svg'"></div>
Mikel
Não é uma solução muito elegante que armazena dados svg em um banco de dados. Não está errado, mas extrair dados DOM xml / html / svg de uma API ou CMS em vez de usar modelos ou outros ativos parece errado.
ChristoKiwi 17/08
Obrigado por esta contribuição ... Os sites mais avançados hoje aninham dados svg para permitir todos os tipos de atividades, sem essa resposta eu não teria imaginado isso!
webMan
Além disso, se o seu SVG tiver áreas transparentes, elas não contarão como pairando e você poderá experimentar "flashy hover". Para corrigir isso, basta adicionar um elemento wrapper (um <a>, se for conveniente) e, em seguida, adicionar à regra CSS. #pathidorclass:hover, .wrapperclass:hover #pathidorclass { fill: green; }Ou até mesmo elimine a focalização original do caminho SVG, já que você está direcionando-o agora através do elemento wrapper.
Neil Monroe
18

@Drew Baker deu uma ótima solução para resolver o problema. O código funciona corretamente. No entanto, quem usa AngularJs pode encontrar muita dependência do jQuery. Consequentemente, achei uma boa ideia colar para usuários do AngularJS, um código que segue a solução de @Drew Baker.

AngularJs maneira do mesmo código

1. Html : use a tag abaixo no seu arquivo html:

<svg-image src="/icons/my.svg" class="any-class-you-wish"></svg-image>

2. Diretiva : será a diretiva que você precisará reconhecer a etiqueta:

'use strict';
angular.module('myApp')
  .directive('svgImage', ['$http', function($http) {
    return {
      restrict: 'E',
      link: function(scope, element) {
        var imgURL = element.attr('src');
        // if you want to use ng-include, then
        // instead of the above line write the bellow:
        // var imgURL = element.attr('ng-include');
        var request = $http.get(
          imgURL,
          {'Content-Type': 'application/xml'}
        );

        scope.manipulateImgNode = function(data, elem){
          var $svg = angular.element(data)[4];
          var imgClass = elem.attr('class');
          if(typeof(imgClass) !== 'undefined') {
            var classes = imgClass.split(' ');
            for(var i = 0; i < classes.length; ++i){
              $svg.classList.add(classes[i]);
            }
          }
          $svg.removeAttribute('xmlns:a');
          return $svg;
        };

        request.success(function(data){
          element.replaceWith(scope.manipulateImgNode(data, element));
        });
      }
    };
  }]);

3. CSS :

.any-class-you-wish{
    border: 1px solid red;
    height: 300px;
    width:  120px
}

4. Teste unitário com karma-jasmim :

'use strict';

describe('Directive: svgImage', function() {

  var $rootScope, $compile, element, scope, $httpBackend, apiUrl, data;

  beforeEach(function() {
    module('myApp');

    inject(function($injector) {
      $rootScope = $injector.get('$rootScope');
      $compile = $injector.get('$compile');
      $httpBackend = $injector.get('$httpBackend');
      apiUrl = $injector.get('apiUrl');
    });

    scope = $rootScope.$new();
    element = angular.element('<svg-image src="/icons/icon-man.svg" class="svg"></svg-image>');
    element = $compile(element)(scope);

    spyOn(scope, 'manipulateImgNode').andCallThrough();
    $httpBackend.whenGET(apiUrl + 'me').respond(200, {});

    data = '<?xml version="1.0" encoding="utf-8"?>' +
      '<!-- Generator: Adobe Illustrator 17.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">' +
      '<!-- Obj -->' +
      '<!-- Obj -->' +
      '<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"' +
      'width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">' +
        '<g>' +
          '<path fill="#F4A902" d=""/>' +
          '<path fill="#F4A902" d=""/>' +
        '</g>' +
      '</svg>';
    $httpBackend.expectGET('/icons/icon-man.svg').respond(200, data);
  });

  afterEach(function() {
    $httpBackend.verifyNoOutstandingExpectation();
    $httpBackend.verifyNoOutstandingRequest();
  });

  it('should call manipulateImgNode atleast once', function () {
    $httpBackend.flush();
    expect(scope.manipulateImgNode.callCount).toBe(1);
  });

  it('should return correct result', function () {
    $httpBackend.flush();
    var result = scope.manipulateImgNode(data, element);
    expect(result).toBeDefined();
  });

  it('should define classes', function () {
    $httpBackend.flush();
    var result = scope.manipulateImgNode(data, element);
    var classList = ["svg"];
    expect(result.classList[0]).toBe(classList[0]);
  });
});
Máx.
fonte
1
sua solução não funciona, poderia ser<div ng-include="/icons/my.svg" class="any-class-you-wish"></div>
Guillaume Vincent
@guillaumevincent se você quiser usá-lo com ng-includeem seguida, basta alterar esta linha var imgURL = element.attr('src');paravar imgURL = element.attr('ng-include');
Max
Essa é uma solução muito útil, mas tenha cuidado ao usá-la, pois pode prejudicar bastante o desempenho - ou seja, um conjunto de 5 ícones de compartilhamento repetidos em uma lista de artigos ou algo assim.
Skxc 11/03/2015
1
Há um problema com o seu código no IE. Você pode usar apenas em if (typeof(imgClass) !== 'undefined') { $svg.setAttribute("class", imgClass); }vez de split e for loop.
Robert Bokori
2
Otimo trabalho! Mas para determinada imagem, você precisa pegar o primeiro elemento do svg ( angular.element(data)[0];) e fazê-lo funcionar com o uso do IE if ($svg.getAttribute('class')) { $svg.setAttribute('class', $svg.getAttribute('class') + ' ' + imgClass); } else { $svg.setAttribute('class', imgClass); }. Além disso, você pode adicionar cache: trueopções às opções, $http.getcaso contrário sua página poderá ficar muito lenta.
leo
16

Sei que você deseja fazer isso com CSS, mas apenas um lembrete, caso seja uma imagem pequena e simples - você sempre pode abri-la no Notepad ++ e alterar o caminho / o preenchimento de qualquer elemento:

<path style="fill:#010002;" d="M394.854,205.444c9.218-15.461,19.102-30.181,14.258-49.527
    ...
    C412.843,226.163,402.511,211.451,394.854,205.444z"/>

Poderia economizar uma tonelada de scripts feios. Desculpe se está fora da base, mas às vezes as soluções simples podem ser negligenciadas.

... mesmo a troca de várias imagens svg pode ser menor em tamanho do que alguns dos trechos de código para esta pergunta.

DShultz
fonte
7

Eu escrevi uma diretiva para resolver esse problema com o AngularJS. Está disponível aqui - ngReusableSvg .

Ele substitui o elemento SVG após sua renderização e o coloca dentro de um divelemento, tornando seu CSS facilmente alterável. Isso ajuda a usar o mesmo arquivo SVG em locais diferentes, usando tamanhos / cores diferentes.

O uso é simples:

<object oa-reusable-svg
        data="my_icon.svg"
        type="image/svg+xml"
        class="svg-class"
        height="30"  // given to prevent UI glitches at switch time
        width="30">
</object>

Depois disso, você pode facilmente ter:

.svg-class svg {
    fill: red; // whichever color you want
}
Omri Aharon
fonte
Olá, obrigado por fornecer esta solução. Eu tentei e produz: <div ng-click = "eventHandler ()" ng-class = "classEventHandler ()" style = "height: 30px; width: 30px; float: left;" class = "svg-class" id = "my-svg" height = "30" width = "30"> [[objeto SVGSVGElement]] </div> No html, basta colocar [[object SVGSVGElement]]. Você sabe qual é o problema? Outra pergunta, isso tem um grande impacto no desempenho ou posso usá-lo em muitos svg's em uma página? E por último, ainda está no angular 1.3 (o pavilhão).
bersling
Qual versão do angular você está usando? Não encontrou seu problema. Talvez seja algo com o SVG? Em termos de desempenho, o switch é relativamente pesado, eu mesmo o usei como 10 e foi bom. Acho que depende da quantidade / tamanho, então teste e experimente. Qual é o problema com o caramanchão? Você está usando uma versão diferente e há um conflito?
Omri Aharon
5

TL / DR: VÁ aqui-> https://codepen.io/sosuke/pen/Pjoqqp

Explicação:

Eu estou assumindo que você tem html algo como isto:

<img src="/img/source.svg" class="myClass">

Definitivamente, siga a rota do filtro, ou seja. seu svg provavelmente é preto ou branco. Você pode aplicar um filtro para obter a cor que desejar, por exemplo, tenho um svg preto que quero verde menta. Primeiro inverti para branco (que é tecnicamente todas as cores RGB cheias) e depois brinquei com a saturação de matiz etc. Para acertar:

filter: invert(86%) sepia(21%) saturate(761%) hue-rotate(92deg) brightness(99%) contrast(107%);

Ainda melhor é que você pode usar uma ferramenta para converter o hexágono que deseja em um filtro para você: https://codepen.io/sosuke/pen/Pjoqqp

AhrenFullStop
fonte
Esta é uma ótima solução apenas para css, além do código de hex para o filtro ser incrível.
Richi González
4

Aqui está uma versão knockout.jsbaseada na resposta aceita:

Importante: Na verdade, também requer jQuery para a substituição, mas achei que poderia ser útil para alguns.

ko.bindingHandlers.svgConvert =
    {
        'init': function ()
        {
            return { 'controlsDescendantBindings': true };
        },

        'update': function (element, valueAccessor, allBindings, viewModel, bindingContext)
        {
            var $img = $(element);
            var imgID = $img.attr('id');
            var imgClass = $img.attr('class');
            var imgURL = $img.attr('src');

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

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

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

                // Replace image with new SVG
                $img.replaceWith($svg);

            }, 'xml');

        }
    };

Em seguida, basta aplicar data-bind="svgConvert: true" a sua tag img.

Essa solução substitui completamente a imgtag por um SVG e quaisquer ligações adicionais não seriam respeitadas.

Simon_Weaver
fonte
2
Isso é ótimo! Se você deseja elevar o nível para o próximo nível, temos uma versão atualizada que inclui armazenamento em cache, portanto, o mesmo SVG não é solicitado duas vezes. github.com/funkhaus/style-guide/blob/master/template/js/…
Drew Baker
Eu estava um pouco preocupado com isso, mas não tive tempo de investigar. Só precisava de algo rápido
Simon_Weaver 1/16
1
@DrewBaker, na verdade, eu estava mais preocupado com o fato de a tag img solicitar o arquivo e depois getsolicitá-lo novamente. Eu considerei mudar o srca um data-srcatributo na imgtag, mas concluiu que os navegadores modernos são suficientes provavelmente inteligente para armazenar em cache o arquivo de qualquer maneira
Simon_Weaver
3

Aqui está um código sem estrutura, apenas js puros:

document.querySelectorAll('img.svg').forEach(function(element) {
            var imgID = element.getAttribute('id')
            var imgClass = element.getAttribute('class')
            var imgURL = element.getAttribute('src')

            xhr = new XMLHttpRequest()
            xhr.onreadystatechange = function() {
                if(xhr.readyState == 4 && xhr.status == 200) {
                    var svg = xhr.responseXML.getElementsByTagName('svg')[0];

                    if(imgID != null) {
                         svg.setAttribute('id', imgID);
                    }

                    if(imgClass != null) {
                         svg.setAttribute('class', imgClass + ' replaced-svg');
                    }

                    svg.removeAttribute('xmlns:a')

                    if(!svg.hasAttribute('viewBox') && svg.hasAttribute('height') && svg.hasAttribute('width')) {
                        svg.setAttribute('viewBox', '0 0 ' + svg.getAttribute('height') + ' ' + svg.getAttribute('width'))
                    }
                    element.parentElement.replaceChild(svg, element)
                }
            }
            xhr.open('GET', imgURL, true)
            xhr.send(null)
        })
user3144480
fonte
3

Existe uma biblioteca de código aberto chamada SVGInject que usa o onloadatributo para disparar a injeção. Você pode encontrar o projeto GitHub em https://github.com/iconfu/svg-inject

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 nosrc atributo

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 os 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
1
Eu gosto mais desta solução, porque cuida de SVGs adicionados dinamicamente.
VickyB 29/01/19
2

Se tivermos um número maior de imagens svg, também podemos ter a ajuda de arquivos de fonte.
Sites como https://glyphter.com/ podem obter um arquivo de fonte do nosso svgs.


Por exemplo

@font-face {
    font-family: 'iconFont';
    src: url('iconFont.eot');
}
#target{
    color: white;
    font-size:96px;
    font-family:iconFont;
}
Abhishek Borar
fonte
5
Eu pessoalmente odeio a técnica "imagens como fonte". Torna difícil adicionar / editar imagens, adiciona muitas marcações sem sentido. Da fonte deve ser fontes, as imagens devem ser imagens etc.
de Drew Baker
Acordado. Você também precisa lembrar / procurar as imagens atribuídas aos caracteres. mas para o caso específico em que as imagens são usadas como ícones / botão / balas, agir mais como texto de mídia, fonte-arquivos também podem ser uma alternativa
Abhishek Borar
mesmo GitHub não use fonte mais para o ícone github.com/blog/2112-delivering-octicons-with-svg
Gagarine
2

Você pode usar a imagem de dados para isso. usando a imagem de dados (URI de dados), você pode acessar o SVG como em linha.

Aqui está o efeito de sobreposição usando CSS e SVG puros.

Eu sei que é uma bagunça, mas você pode fazer assim.

 .action-btn {
    background-size: 20px 20px;
    background-position: center center;
    background-repeat: no-repeat;
    border-width: 1px;
    border-style: solid;
    border-radius: 30px;
    height: 40px;
    width: 60px;
    display: inline-block;
 }

.delete {
     background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg version='1.1' id='Capa_1' fill='#FB404B' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='482.428px' height='482.429px' viewBox='0 0 482.428 482.429' style='enable-background:new 0 0 482.428 482.429;' xml:space='preserve'%3e%3cg%3e%3cg%3e%3cpath d='M381.163,57.799h-75.094C302.323,25.316,274.686,0,241.214,0c-33.471,0-61.104,25.315-64.85,57.799h-75.098 c-30.39,0-55.111,24.728-55.111,55.117v2.828c0,23.223,14.46,43.1,34.83,51.199v260.369c0,30.39,24.724,55.117,55.112,55.117 h210.236c30.389,0,55.111-24.729,55.111-55.117V166.944c20.369-8.1,34.83-27.977,34.83-51.199v-2.828 C436.274,82.527,411.551,57.799,381.163,57.799z M241.214,26.139c19.037,0,34.927,13.645,38.443,31.66h-76.879 C206.293,39.783,222.184,26.139,241.214,26.139z M375.305,427.312c0,15.978-13,28.979-28.973,28.979H136.096 c-15.973,0-28.973-13.002-28.973-28.979V170.861h268.182V427.312z M410.135,115.744c0,15.978-13,28.979-28.973,28.979H101.266 c-15.973,0-28.973-13.001-28.973-28.979v-2.828c0-15.978,13-28.979,28.973-28.979h279.897c15.973,0,28.973,13.001,28.973,28.979 V115.744z'/%3e%3cpath d='M171.144,422.863c7.218,0,13.069-5.853,13.069-13.068V262.641c0-7.216-5.852-13.07-13.069-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C158.074,417.012,163.926,422.863,171.144,422.863z'/%3e%3cpath d='M241.214,422.863c7.218,0,13.07-5.853,13.07-13.068V262.641c0-7.216-5.854-13.07-13.07-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C228.145,417.012,233.996,422.863,241.214,422.863z'/%3e%3cpath d='M311.284,422.863c7.217,0,13.068-5.853,13.068-13.068V262.641c0-7.216-5.852-13.07-13.068-13.07 c-7.219,0-13.07,5.854-13.07,13.07v147.154C298.213,417.012,304.067,422.863,311.284,422.863z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e ");
     border-color:#FB404B;
     
 }
 
 .delete:hover {
     background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg version='1.1' id='Capa_1' fill='#fff' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='482.428px' height='482.429px' viewBox='0 0 482.428 482.429' style='enable-background:new 0 0 482.428 482.429;' xml:space='preserve'%3e%3cg%3e%3cg%3e%3cpath d='M381.163,57.799h-75.094C302.323,25.316,274.686,0,241.214,0c-33.471,0-61.104,25.315-64.85,57.799h-75.098 c-30.39,0-55.111,24.728-55.111,55.117v2.828c0,23.223,14.46,43.1,34.83,51.199v260.369c0,30.39,24.724,55.117,55.112,55.117 h210.236c30.389,0,55.111-24.729,55.111-55.117V166.944c20.369-8.1,34.83-27.977,34.83-51.199v-2.828 C436.274,82.527,411.551,57.799,381.163,57.799z M241.214,26.139c19.037,0,34.927,13.645,38.443,31.66h-76.879 C206.293,39.783,222.184,26.139,241.214,26.139z M375.305,427.312c0,15.978-13,28.979-28.973,28.979H136.096 c-15.973,0-28.973-13.002-28.973-28.979V170.861h268.182V427.312z M410.135,115.744c0,15.978-13,28.979-28.973,28.979H101.266 c-15.973,0-28.973-13.001-28.973-28.979v-2.828c0-15.978,13-28.979,28.973-28.979h279.897c15.973,0,28.973,13.001,28.973,28.979 V115.744z'/%3e%3cpath d='M171.144,422.863c7.218,0,13.069-5.853,13.069-13.068V262.641c0-7.216-5.852-13.07-13.069-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C158.074,417.012,163.926,422.863,171.144,422.863z'/%3e%3cpath d='M241.214,422.863c7.218,0,13.07-5.853,13.07-13.068V262.641c0-7.216-5.854-13.07-13.07-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C228.145,417.012,233.996,422.863,241.214,422.863z'/%3e%3cpath d='M311.284,422.863c7.217,0,13.068-5.853,13.068-13.068V262.641c0-7.216-5.852-13.07-13.068-13.07 c-7.219,0-13.07,5.854-13.07,13.07v147.154C298.213,417.012,304.067,422.863,311.284,422.863z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e ");        
     background-color: #FB404B;
    }
<a class="action-btn delete">&nbsp;</a>

Você pode converter seu svg em url de dados aqui

  1. https://codepen.io/elliz/full/ygvgay
  2. https://websemantics.uk/tools/svg-to-background-image-conversion/
patelarpan
fonte
Isso não funcionaria para SVGs complexos, nos quais você deseja que apenas certos caminhos / polígonos / etc. sejam alterados ao passar o mouse, certo?
Drew Baker
Não, você can..but-lo muito complexo
patelarpan
Ele soluções apenas para icon
patelarpan
Se algum trabalho com ícone. Então é ótimo. Bootstrap 4 também usar esta técnica
patelarpan
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:

  1. Mozilla Firefox 59.0.2 (64 bits) Linux

insira a descrição da imagem aqui

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

insira a descrição da imagem aqui

  1. Opera 53.0.2907.37 Linux

insira a descrição da imagem aqui

Benjamin
fonte
1

A solução selecionada é boa se você quiser que o jQuery processe todos os elementos svg no seu DOM e seu DOM seja de tamanho razoável. Mas se o seu DOM for grande e você decidir carregar partes do seu DOM dinamicamente, realmente não faz sentido ter que varrer novamente todo o DOM apenas para atualizar os elementos svg. Em vez disso, use um plugin jQuery para fazer isso:

/**
 * A jQuery plugin that loads an svg file and replaces the jQuery object with its contents.
 *
 * The path to the svg file is specified in the src attribute (which normally does not exist for an svg element).
 *
 * The width, height and class attributes in the loaded svg will be replaced by those that exist in the jQuery object's
 * underlying html. Note: All other attributes in the original element are lost including the style attribute. Place
 * any styles in a style class instead.
 */
(function ($) {
    $.fn.svgLoader = function () {
        var src = $(this).attr("src");
        var width = this.attr("width");
        var height = this.attr("height");
        var cls = this.attr("class");
        var ctx = $(this);

        // Get the svg file and replace the <svg> element.
        $.ajax({
            url: src,
            cache: false
        }).done(function (html) {
            let svg = $(html);
            svg.attr("width", width);
            svg.attr("height", height);
            svg.attr("class", cls);
            var newHtml = $('<a></a>').append(svg.clone()).html();
            ctx.replaceWith(newHtml);
        });

        return this;
    };

}(jQuery));

No seu html, especifique um elemento svg da seguinte maneira:

<svg src="images/someSvgFile.svg" height="45" width="45" class="mySVGClass"/>

E aplique o plugin:

$(".mySVGClass").svgLoader();
AndroidDev
fonte
Sim, certamente existem maneiras mais eficientes de usar o código que eu dei. Aqui está como realmente o usamos em sites de produção. Ele armazena em cache SVGs! github.com/funkhaus/style-guide/blob/master/template/js/...
de Drew Baker
1

para: animações de evento pairar, podemos deixar os estilos dentro do arquivo svg, como um

<svg xmlns="http://www.w3.org/2000/svg">
<defs>
  <style>
  rect {
    fill:rgb(165,225,75);
    stroke:none;
    transition: 550ms ease-in-out;
    transform-origin:125px 125px;
  }
  rect:hover {
    fill:rgb(75,165,225);
    transform:rotate(360deg);
  }
  </style>
</defs>
  <rect x='50' y='50' width='150' height='150'/>
</svg>

verifique isso no svgshare

ghett
fonte