¿Cómo cambiar el color de la imagen SVG usando CSS (reemplazo de imagen SVG jQuery)?

437

Este es un Q&A propio de un útil código que se me ocurrió.

Actualmente, no hay una manera fácil de incrustar una imagen SVG y luego tener acceso a los elementos SVG a través de CSS. Existen varios métodos para usar los marcos JS SVG, pero son demasiado complicados si todo lo que está haciendo es crear un icono simple con un estado de sustitución.

Entonces, esto es lo que se me ocurrió, que creo que es, con mucho, la forma más fácil de usar archivos SVG en un sitio web. Toma su concepto de los primeros métodos de reemplazo de texto a imagen, pero que yo sepa, nunca se ha hecho para SVG.

Esta es la pregunta:

¿Cómo incrusto un SVG y cambio su color en CSS sin usar un marco JS-SVG?

Drew Baker
fuente
1
Desafortunadamente, la etiqueta img no funciona con archivos svg en IE, así que tenlo en cuenta. IE reconoce etiquetas incrustadas. De todos modos, buen trabajo!
2
Para svg, debe usar la propiedad css "fill". Para las imágenes es apropiado usar "filtro". De hecho, "Filtro" funciona para ambos, pero no es necesario hacer todo ese trabajo para un gráfico vectorial.
Samy Bencherif

Respuestas:

536

En primer lugar, use una etiqueta IMG en su HTML para incrustar un gráfico SVG. Usé Adobe Illustrator para hacer el gráfico.

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

Así es como incrustar una imagen normal. Tenga en cuenta que debe configurar el IMG para que tenga una clase de svg. La clase 'social-link' es solo por ejemplo. La identificación no es obligatoria, pero es útil.

Luego use este código jQuery (en un archivo separado o en línea en el 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');

        });

Lo que hace el código anterior es buscar todos los IMG con la clase 'svg' y reemplazarlo con el SVG en línea del archivo vinculado. La gran ventaja es que le permite usar CSS para cambiar el color del SVG ahora, así:

svg:hover path {
    fill: red;
}

El código jQuery que escribí también tiene puertos a través de las imágenes y el ID de las imágenes originales. Entonces este CSS también funciona:

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

O:

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

Puede ver un ejemplo de esto trabajando aquí: http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html

Tenemos una versión más complicada que incluye el almacenamiento en caché aquí: https://github.com/funkhaus/style-guide/blob/master/template/js/site.js#L32-L90

Drew Baker
fuente
66
A veces puede no funcionar en Safari (por ejemplo), para garantizar que los datos devueltos sean legibles, });vuelva a colocar el de $ .get con}, 'xml');
Joan
29
Probablemente incluso podría reemplazar el selector con img[src$=".svg"]y eliminar la necesidad de la svgclase.
Casey Chu el
2
@LeonGaban No creo que haya una manera de apuntar al relleno de una imagen de fondo. ¡Sería súper útil si pudieras!
Drew Baker el
3
Un poco tarde, @LeonGaban, pero una mejor manera de hacerlo probablemente sería eliminar el atributo de relleno por completo y confiar en un archivo CSS para agregar un relleno al svg principal. $('#ico_company path').removeAttr('fill'). Entonces podría hacerlo #ico_company { fill: #ccc }en su archivo CSS
bioball
2
@Soaku sería fácil hacer que jQuery configure todas las rutas para que sean iguales al color de fuente haciendo algo como `var color = $ img.closest ('p'). Css ('color'); $ svg.find ('ruta'). attr ('relleno', color); `Pero creo que este es un trabajo mejor dejado a CSS.
Drew Baker,
56

Estilo

svg path {
    fill: #000;
}

Guión

$(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
fuente
1
Si no tiene un ancho de atributo, solo crea uno con un número incorrecto. width="170.667"en mi caso
stallingOne
2
Esto no es perfecto ya que pierde las dimensiones img anteriores.
RichieHH
Hola, supongamos que tengo diferentes svg con diferentes colores de red cada uno. Usando este método, todos mis colores de svg se vuelven iguales que el primer svg que se está en bucle. ¿Alguna idea de cómo puedo maniobrar alrededor de esto para que cada color permanezca igual que antes?
tnkh
1
tenga en cuenta que si su svg está hecho también de no pathformas (como rect), también necesitará manejarlos en CSS
Mugen
33

Ahora puede usar la propiedad CSSfilter en la mayoría de los navegadores modernos (incluido Edge, pero no IE11). Funciona en imágenes SVG, así como en otros elementos. Puede usar hue-rotateo invertmodificar colores, aunque no le permiten modificar diferentes colores de forma independiente. Utilizo la siguiente clase CSS para mostrar una versión "deshabilitada" de un icono (donde el original es una imagen SVG con color saturado):

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

Esto lo hace gris claro en la mayoría de los navegadores. En IE (y probablemente Opera Mini, que no he probado), la propiedad de opacidad se desvanece notablemente, que todavía se ve bastante bien, aunque no es gris.

Aquí hay un ejemplo con cuatro clases CSS diferentes para el ícono de la campana Twemoji : original (amarillo), la clase "deshabilitada" anterior, hue-rotate(verde) y invert(azul).

Aldel
fuente
Acabo de notar que invertir es una buena solución si no desea crear fuentes de iconos. Utilicé este código jQuery para cambiar el ícono en el encabezado de mi sitio web de acuerdo con la propiedad de color css (observe que estoy usando íconos png blancos):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
Gran enfoque Edité mi SVG xml para agregar el color del icono de destino y luego usé una clase .icon-disabled para atenuarlo.
SushiGuy
Tenga en cuenta que el antiguo Explores no admite el filtro: w3schools.com/cssref/css3_pr_filter.asp
JillAndMe
25

Alternativamente, podría usar CSS mask, el soporte del navegador no es bueno, pero podría usar un respaldo

.frame {
    background: blue;
    -webkit-mask: url(image.svg) center / contain no-repeat;
}
seanjacob
fuente
14
MDN especifica que -webkit-maskno debe usarse en ningún sitio web de producción.
vaindil
1
no colorea el svg
vishal
Tal vez sea relevante decir que ahora, cuatro años después, esta solución está funcionando en todos los principales navegadores. Acabo de probar aquí y está 100% bien.
Daniel Lemes
23

Si puede incluir archivos (PHP incluye o incluye a través de su CMS de elección) en su página, puede agregar el código SVG e incluirlo en su página. Esto funciona igual que pegar la fuente SVG en la página, pero hace que el marcado de la página sea más limpio.

El beneficio es que puede apuntar a partes de su SVG a través de CSS para pasar el mouse por encima, no se requiere JavaScript.

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

Solo tiene que usar una regla CSS como esta:

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

Tenga en cuenta que el !importantbit es necesario para anular el color de relleno.

trebor1979
fuente
3
Para aquellos que usan AngularJS:<div ng-include="'svg.svg'"></div>
Mikel
Sin embargo, no es una solución muy elegante para almacenar datos svg en una base de datos. No está mal, pero extraer datos DOM xml / html / svg de una API o CMS en lugar de usar plantillas u otros activos simplemente se siente mal.
ChristoKiwi
Gracias por esta contribución ... Los sitios más avanzados de hoy anidan datos de svg para permitir todo tipo de actividad, ¡sin esta respuesta no lo habría adivinado!
webMan
Además, si su SVG tiene áreas transparentes, estas no contarán como flotantes y puede experimentar un "flotante llamativo". Para solucionarlo, solo agregue un elemento contenedor (un <a>, si es conveniente) y luego agréguelo a la regla CSS. #pathidorclass:hover, .wrapperclass:hover #pathidorclass { fill: green; }O incluso simplemente elimine el elemento emergente original de la ruta SVG ya que de todos modos ahora lo está apuntando a través del elemento contenedor.
Neil Monroe
18

@Drew Baker dio una gran solución para resolver el problema. El código funciona correctamente. Sin embargo, aquellos que usan AngularJs pueden encontrar mucha dependencia en jQuery. En consecuencia, pensé que es una buena idea pegar para los usuarios de AngularJS, un código que sigue la solución de @Drew Baker.

AngularJs forma del mismo código

1. Html : use la etiqueta de abajo en su archivo html:

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

2. Directiva : esta será la directiva que necesitará para reconocer la 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. Prueba de unidad con karma-jazmín :

'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]);
  });
});
Max
fuente
1
su solución no funciona, podría ser<div ng-include="/icons/my.svg" class="any-class-you-wish"></div>
Guillaume Vincent
@guillaumevincent si quieres usarlo, ng-includeentonces simplemente cambia esta línea var imgURL = element.attr('src');avar imgURL = element.attr('ng-include');
Max
Esta es una solución muy útil, pero tenga cuidado al usarla en exceso, ya que puede afectar el rendimiento bastante duro: es decir, un conjunto de 5 iconos para compartir que se repiten en una lista de artículos o algo así.
skxc
1
Hay un problema con su código en IE. Puede usar solo en if (typeof(imgClass) !== 'undefined') { $svg.setAttribute("class", imgClass); }lugar de dividir y para bucle.
Robert Bokori
2
¡Impresionante trabajo! Pero para cierta imagen, debe tomar el primer elemento de svg ( angular.element(data)[0];) y hacer que funcione con el uso de IE if ($svg.getAttribute('class')) { $svg.setAttribute('class', $svg.getAttribute('class') + ' ' + imgClass); } else { $svg.setAttribute('class', imgClass); }. También es posible que desee agregar cache: truea las opciones de lo $http.getcontrario, su página podría volverse muy lenta.
leo
16

Me doy cuenta de que desea lograr esto con CSS, pero solo un recordatorio en caso de que sea una imagen pequeña y simple: siempre puede abrirlo en Notepad ++ y cambiar la ruta / relleno de Whaleverelement:

<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"/>

Podría salvar un montón de guiones feos. Lo siento si está fuera de la base, pero a veces las soluciones simples pueden pasarse por alto.

... incluso el intercambio de múltiples imágenes svg puede ser más pequeño que algunos de los fragmentos de código para esta pregunta.

DShultz
fuente
7

Escribí una directiva para resolver este problema con AngularJS. Está disponible aquí: ngReusableSvg .

Reemplaza el elemento SVG después de que se ha renderizado y lo coloca dentro de un divelemento, haciendo que su CSS sea fácilmente cambiable. Esto ayuda a usar el mismo archivo SVG en diferentes lugares usando diferentes tamaños / colores.

El uso es simple:

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

Después de eso, puede tener fácilmente:

.svg-class svg {
    fill: red; // whichever color you want
}
Omri Aharon
fuente
Hola, gracias por brindar esta solución. Lo he intentado y produce: <div ng-click = "eventHandler ()" ng-class = "classEventHandler ()" style = "height: 30px; width: 30px; float: left;" class = "svg-class" id = "my-svg" height = "30" width = "30"> [[object SVGSVGElement]] </div> En el html simplemente pone [[object SVGSVGElement]]. ¿Sabes cuál es el problema? Otra pregunta, ¿tiene un gran impacto en el rendimiento o puedo usarlo en muchos svg en una página? Y, por último, todavía está en angular 1.3 (la glorieta).
bersling
¿Qué versión de angular estás usando? No he encontrado tu problema ... ¿tal vez es algo con el SVG? En cuanto al rendimiento, el cambio es relativamente pesado, lo he usado yo mismo como 10 y estuvo bien ... Supongo que eso depende de la cantidad / tamaño, así que prueba y experimenta con él. ¿Cuál es el problema con la glorieta? ¿Estás usando una versión diferente y hay un conflicto?
Omri Aharon
5

TL / DR: IR aquí-> https://codepen.io/sosuke/pen/Pjoqqp

Explicación:

Supongo que tienes html algo como esto:

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

Definitivamente ir a la ruta del filtro, es decir. su svg probablemente sea blanco o negro. Puede aplicar un filtro para que sea del color que desee, por ejemplo, tengo un svg negro que quiero verde menta. Primero lo invierto para que sea blanco (que es técnicamente todos los colores RGB en su totalidad), luego juego con la saturación de tono, etc. Para hacerlo bien:

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

Aún mejor es que podría usar una herramienta para convertir el hexadecimal que desea en un filtro para usted: https://codepen.io/sosuke/pen/Pjoqqp

AhrenFullStop
fuente
Esta es una gran solución solo para CSS, además el codepen de hexadecimal a filtro es simplemente increíble.
Richi González
4

Aquí hay una versión knockout.jsbasada en la respuesta aceptada:

Importante: En realidad, también requiere jQuery para el reemplazo, pero pensé que puede ser útil para algunos.

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');

        }
    };

Luego solo aplica data-bind="svgConvert: true"a tu etiqueta img.

Esta solución reemplaza completamente la imgetiqueta con un SVG y no se respetarán los enlaces adicionales.

Simon_Weaver
fuente
2
¡Esto es genial! Si desea llevarlo al siguiente nivel, tenemos una versión actualizada que incluye el almacenamiento en caché, por lo que no se solicita el mismo SVG dos veces. github.com/funkhaus/style-guide/blob/master/template/js/…
Drew Baker
Estaba un poco preocupado por eso, pero no tuve tiempo de investigarlo yo mismo. Solo necesitaba algo rápido
Simon_Weaver
1
@DrewBaker en realidad estaba más preocupado porque la etiqueta img solicitaría el archivo y luego getlo solicitaría nuevamente. Pensé en cambiarlo srca un data-srcatributo en la imgetiqueta, pero concluí que los navegadores modernos probablemente sean lo suficientemente inteligentes como para almacenar en caché el archivo de todos modos
Simon_Weaver,
3

Aquí hay un código sin marco, solo js puro:

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)
        })
usuario3144480
fuente
3

Hay una biblioteca de código abierto llamada SVGInject que usa el onloadatributo para activar la inyección. Puede encontrar el proyecto GitHub en https://github.com/iconfu/svg-inject

Aquí hay un ejemplo mínimo con SVGInject:

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

Después de cargar la imagen onload="SVGInject(this), activará la inyección y el <img>elemento será reemplazado por el contenido del archivo SVG provisto en elsrc atributo.

Resuelve varios problemas con la inyección de SVG:

  1. Los SVG pueden ocultarse hasta que finalice la inyección. Esto es importante si un estilo ya se aplica durante el tiempo de carga, lo que de otro modo causaría un breve "destello de contenido sin estilo".

  2. Los <img>elementos se inyectan automáticamente. Si agrega SVG dinámicamente, no tiene que preocuparse por volver a llamar a la función de inyección.

  3. Se agrega una cadena aleatoria a cada ID en el SVG para evitar tener el mismo ID varias veces en el documento si se inyecta un SVG más de una vez.

SVGInject es Javascript simple y funciona con todos los navegadores que admiten SVG.

Descargo de responsabilidad: soy coautor de SVGInject

Waruyama
fuente
1
Esta solución me gusta más, porque se encarga de SVG añadidos dinámicamente.
VickyB
2

Si tenemos un mayor número de tales imágenes svg, también podemos tomar la ayuda de archivos de fuentes.
Sitios como https://glyphter.com/ pueden obtenernos un archivo de fuente de nuestros svgs.


P.ej

@font-face {
    font-family: 'iconFont';
    src: url('iconFont.eot');
}
#target{
    color: white;
    font-size:96px;
    font-family:iconFont;
}
Abhishek Borar
fuente
55
Personalmente odio la técnica de "imágenes como fuente". Hace que sea difícil agregar / editar imágenes, agrega muchas marcas sin sentido. Las fuentes deben ser fuentes, las imágenes deben ser imágenes, etc.
Drew Baker
Convenido. También debe recordar / buscar las imágenes asignadas a los personajes. pero para el caso específico en el que las imágenes se utilizan como iconos / botón / balas, actúan más como texto de los medios de comunicación, de Font-archivos también pueden ser una alternativa
Abhishek Borar
incluso github ya no usa la fuente para el icono github.com/blog/2112-delivering-octicons-with-svg
gagarine
2

Puedes usar data-image para eso. usando data-image (data-URI) puede acceder a SVG como en línea.

Aquí está el efecto de rollover usando CSS puro y SVG.

Lo sé desordenado, pero puedes hacerlo de esta manera.

 .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>

Puede convertir su svg a url de datos aquí

  1. https://codepen.io/elliz/full/ygvgay
  2. https://websemantics.uk/tools/svg-to-background-image-conversion/
patelarpan
fuente
Esto no funcionaría para SVG complejos donde solo desea que ciertas rutas / polígonos / etc. cambien al pasar el mouse, ¿verdad?
Drew Baker,
No puedes ... pero es muy complejo
patelarpan
Solo soluciones para íconos
patelarpan
Si algunos funcionan con el icono. Entonces es genial. Bootstrap 4 también usa esta técnica
patelarpan
2

Dado que SVG es básicamente código, solo necesita contenido. Usé PHP para obtener contenido, pero puedes usar lo que quieras.

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

Luego, imprimí el contenido "tal cual" dentro de un contenedor div

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

Para finalmente establecer la regla en los hijos SVG del contenedor en CSS

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

Obtuve estos resultados con un icono de material SVG:

  1. Mozilla Firefox 59.0.2 (64 bits) Linux

ingrese la descripción de la imagen aquí

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

ingrese la descripción de la imagen aquí

  1. Opera 53.0.2907.37 Linux

ingrese la descripción de la imagen aquí

Benjamín
fuente
1

La solución seleccionada está bien si desea que jQuery procese todos los elementos svg en su DOM y su DOM tenga un tamaño razonable. Pero si su DOM es grande y decide cargar partes de su DOM dinámicamente, realmente no tiene sentido tener que volver a escanear todo el DOM solo para actualizar los elementos svg. En su lugar, use un complemento jQuery para hacer esto:

/**
 * 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));

En su html, especifique un elemento svg de la siguiente manera:

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

Y aplique el complemento:

$(".mySVGClass").svgLoader();
AndroidDev
fuente
Sí, ciertamente hay formas más eficientes de usar el código que di. Así es como lo usamos en los sitios de producción. ¡Caché SVG! github.com/funkhaus/style-guide/blob/master/template/js/…
Drew Baker
1

para: animaciones de eventos flotantes podemos dejar los estilos dentro del archivo svg, como un

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

mira esto en svgshare

ghett
fuente