img src SVG cambiando los estilos con CSS

374

html

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

css

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

El svg anterior se carga y es nativo, fill: #fffpero cuando uso el anterior csspara intentar cambiarlo a negro no cambia, esta es la primera vez que juego con SVG y no estoy seguro de por qué no funciona.

ngplayground
fuente
25
No puede afectar imágenes SVG como esa ... solo elementos SVG en línea
Paulie_D
Verifique mi respuesta aquí para usar los contenidos de SVG y CSS. stackoverflow.com/questions/11978995/…
Benjamin

Respuestas:

153

Si su objetivo es solo cambiar el color del logotipo, y no necesariamente NECESITA usar CSS, entonces no use javascript o jquery como se sugirió en algunas respuestas anteriores.

Para responder con precisión la pregunta original, solo:

  1. Abre tu logo.svgen un editor de texto.

  2. búsquelo fill: #fffy reemplácelo confill: #000

Por ejemplo, logo.svgpodría verse así cuando se abre en un 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>

... solo cambia el relleno y guarda.

Rowe Morehouse
fuente
66
... y si no hay un "relleno", sólo puede añadir a la patho circleartículos como <path fill="#777777" d="m129.774,74.409c-5.523,....
SaeX
1
¿Qué pasa si mi logotipo tiene un color en el encabezado y otro color en el pie de página?
rubens.lopes
. @ ruben.lopes dos archivos diferentes, o dos líneas diferentes serían más simples
Rowe Morehouse
11
también puede usar el y fill="currentColor"luego usar el colorelemento primario css-tricks.com/cascading-svg-fill-color
Serge
10
Obviamente, esto es posible y no es realmente una respuesta útil.
Timmmm
101

Puedes configurar tu SVG como una máscara. De esa manera, establecer un color de fondo actuaría como su color de relleno.

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

Compruebe si su navegador admite esta función: https://caniuse.com/#search=mask

André Kuhlmann
fuente
3
Entonces, para cualquier cosa menos sitio web interno inutilizable.
Henrik Vendelbo
99
89% de apoyo global a partir del 29 de mayo de 2016.
Gajus
1
Esta es una solución sorprendente para situaciones como la que se describe aquí , en la que usar algo más que datos uris en css es un poco difícil. ¡Gracias!
Gark Garcia el
3
no funciona. dice que maskes un invalid property value. Estoy probando esto en Chrome.
Eren555
1
@MadMac Estoy ejecutando la misma versión de Chrome, pero no pude replicar ese comportamiento. ¿Es el JSFiddle que probaste o tu código?
André Kuhlmann
78

Prueba CSS puro:

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

Más información en este artículo https://blog.union.io/code/2017/08/10/img-svg-fill/

Feri
fuente
Estaba obteniendo un color diferente en Edge que en otros navegadores con uno de mis intentos recientemente.
Julix
44
Esto funciona en la mayoría de los navegadores, pero tuve algunos problemas con el navegador IOS-Safari.
Simon Ludwig el
31

2018: si desea un color dinámico, no desea usar javascript y no desea un SVG en línea, use una variable CSS. Funciona en Chrome, Firefox y Safari. editar: y Edge

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

En su SVG, reemplace cualquier instancia de style="fill: #000"con style="fill: var(--color_fill)".

norteamericana
fuente
1
¿Cuál es el soporte de los navegadores para este
Kevin Goedecke
@KevinGoedecke Chrome, Firefox, Safari y Edge
norteamericano
44
Parece obsoleto en SVG 2
vsync
55
@northamerican: los enlaces a otras respuestas de stackoverflow como "pruebas" son irrelevantes. Cualquiera puede escribir cualquier cosa en esta 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:hrefestá en desuso a favor de href. Entonces esto puede funcionar.
Benjamin Intal el
20

Primero tendrá que inyectar el SVG en el DOM HTML.

Hay una biblioteca de código abierto llamada SVGInject que hace esto por usted. Utiliza el onloadatributo para desencadenar la inyección.

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
3
Esta es la respuesta más directa. Lo probé en Chrome, Firefox y Edge y funciona perfectamente.
Sébastien Lorion
15

La respuesta de @Praveen es sólida.

No pude lograr que respondiera en mi trabajo, así que hice una función de desplazamiento de jquery para ello.

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
fuente
1
¿no funcionaría esto si SVG estuviera en línea para empezar?
Daniel Thompson
Sí, pero si está trabajando con muchos archivos SVG o actualizándolos regularmente, es difícil de manejar.
Matt Wujek
15

¿Por qué no crear una fuente web con su imagen o imágenes svg, importar la fuente web en el CSS y luego simplemente cambiar el color del glifo utilizando el atributo de color CSS? No se necesita javascript

gringo
fuente
55
Si su svg tiene varios elementos de diferentes colores, esta solución se vuelve muy hacky (varios elementos interpuestos).
kakaja
1
@kakaja Esta es una solución solo para imágenes vectoriales que tienen 1 color. vea la respuesta de bpulecio para más detalles
gringo
1
Porque el icono no es texto. Las fuentes son para texto. Los SVG son para iconos.
Lazar Ljubenović
2
@ LazarLjubenović: técnicamente el texto está hecho de caracteres que son símbolos, y los íconos también son símbolos, por eso muchos no tienen problemas para usar fuentes de íconos. es como crear "otro" lenguaje textual. El mandarín usa "iconos" y no letras también, no es raro en la humanidad usar iconos como "texto"
vsync
1
Si bien esto suena como una solución interesante, realmente recomiendo elaborar la respuesta en algo más como "cómo" en lugar de "por qué no"
YakovL
15

Esta respuesta se basa en la respuesta https://stackoverflow.com/a/24933495/3890888 pero con una versión simple de JavaScript del script utilizado allí.

Debe hacer que el SVG sea un SVG en línea . Puede utilizar este script agregando una clase svga la imagen:

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

    });

});

Y luego, ahora si lo haces:

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

O tal vez:

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

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

Seb3736
fuente
1
Grandes obras. Además, si nuestra página tiene varios archivos SVG, tendremos que colocar el bloque fetch en el IIFE.
Sandeep Sharma
1
¡Excelente! Funciona bien con ES6. Si no te importa IE 9, incluso puedes usar: parser.parseFromString(text, "image/svg+xml");
ChristoKiwi
No funciona en un UIWebView en iOS 9.3.5. Yo creo que podría ser debido al uso de fetchque se añadió a Safari en 10.1 ( developer.mozilla.org/en-US/docs/Web/API/Fetch_API ). La versión de jQuery anterior funciona.
Maria-Ines Carrera
7

Use filtros para transformar a cualquier color.

Recientemente encontré esta solución, y espero que alguien pueda usarla. Como la solución usa filtros, se puede usar con cualquier tipo de imagen. No solo svg.

Si tiene una imagen de un solo color de la que solo desea cambiar el color, puede hacerlo con la ayuda de algunos filtros. También funciona en imágenes multicolores, por supuesto, pero no puede seleccionar un color específico. Solo la imagen completa.

Los filtros provienen del script propuesto en Cómo transformar el negro en cualquier color usando solo filtros CSS. Si desea cambiar el blanco a cualquier color, puede ajustar el valor invertido en 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
fuente
5

Si solo está cambiando la imagen entre el color real y el blanco y negro, puede configurar un selector como:

{filtro: ninguno;}

y otro como:

{filter:grayscale(100%);}
wcb1
fuente
4

Para expandir la respuesta @gringo, el método Javascript descrito en otras respuestas funciona, pero requiere que el usuario descargue archivos de imagen innecesarios y, en mi opinión, hincha el código.

Creo que un mejor enfoque sería migrar todos los gráficos vectoriales de 1 color a un archivo de fuente web. He usado Fort Awesome en el pasado, y funciona muy bien para combinar sus íconos / imágenes personalizados en formato SVG, junto con cualquier ícono de terceros que pueda estar usando (Font Awesome, íconos Bootstrap, etc.) en un solo archivo de fuente web El usuario tiene que descargar. También puede personalizarlo, por lo que solo incluye los iconos de terceros que está utilizando. Esto reduce la cantidad de solicitudes que debe realizar la página y su peso general, especialmente si ya incluye bibliotecas de iconos de terceros.

Si prefiere una opción más orientada al desarrollo, puede buscar en Google "npm svg webfont" y usar uno de los módulos de nodo más adecuados para su entorno.

Una vez que haya hecho cualquiera de esas dos opciones, podría cambiar fácilmente el color a través de CSS, y lo más probable es que haya acelerado su sitio en el proceso.

bpulecio
fuente
Deberías probar los sprites SVG. En mi experiencia, las fuentes web tienen problemas aleatorios entre las versiones del navegador. Pruebe esto: fontastic.me , pero use las versiones de sprites SVG, y vea lo que piensa. :)
sheriffderek
3

Simple..

Puedes usar este código:

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

Primero especifique la ruta de svg y luego escriba su ID, en este caso "Capa_1". Puede obtener la identificación de svg abriéndola en cualquier editor.

En css:

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

El principal problema en su caso es que está importando el svg desde una <img>etiqueta que ocultará la estructura SVG.

Debe usar la <svg>etiqueta junto con el <use>para obtener el efecto deseado. Para que funcione, debe asignar un idcamino a la ruta que desea usar en el archivo SVG <path id='myName'...>para poder recuperarlos de la <use xlink:href="#myName"/>etiqueta. Prueba el recortado a continuación.

Tenga en cuenta que puede colocar cualquier URL antes del fragmento #si desea cargar el SVG desde una fuente externa (y no incrustarlo en su HTML). Además, normalmente no especifica el relleno en el CSS. Es mejor considerar usar fill:"currentColor"dentro del SVG. El valor de color CSS del elemento correspondiente se utilizará en su lugar.

Flavien Volken
fuente
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:

Mozilla Firefox 59.0.2 (64 bits) Linux

ingrese la descripción de la imagen aquí

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

ingrese la descripción de la imagen aquí

Opera 53.0.2907.37 Linux

ingrese la descripción de la imagen aquí

Benjamín
fuente
No puedo rechazar, pero por favor nunca hagas esto.
lijadora
55
¿Razones? ¿Alternativas?
Benjamin
Mi razón para no hacer esto es que esto evita que el navegador almacene en caché el SVG. La alternativa es utilizar un inyector SVG mencionado en algunas otras respuestas aquí. El archivo SVG seguirá siendo almacenado en caché por el navegador, y el SVG inyectado aún puede ser diseñado con CSS. Pero no te menosprecio.
Sơn Trần-Nguyễn
Entiendo, pero de todos modos, el caché no se menciona. La mejor respuesta tiene un código JavaScript que se puede recargar (o no) cada vez mediante la manipulación de la caducidad del encabezado o forzar un hash después del enlace del nombre de archivo.
Benjamin
2

Esto podría ser útil para las personas que usan PHPen combinación con .svgimágenes que desean manipular con CSS.

No puede sobrescribir propiedades dentro de una etiqueta img con CSS. Pero cuando el código fuente de svg está incrustado en el HTML, seguramente puede hacerlo. Me gusta resolver este problema con una require_oncefunción donde incluyo un .svg.phparchivo. ¡Es como importar una imagen pero aún puede sobrescribir estilos con CSS!

Primero incluye el archivo svg:

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

E incluye este icono, por ejemplo:

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

Ahora podemos cambiar fácilmente el color de relleno de esta manera con CSS:

svg path {
  fill: blue;
}

Primero intenté resolver este problema, file_get_contents()pero la solución anterior es mucho más rápida.

Floris
fuente
0

Sepa que esta es una pregunta antigua, pero recientemente encontramos el mismo problema y lo resolvimos desde el lado del servidor. Esta es una respuesta específica de php, pero estoy seguro de que otros envs tienen algo similar. en lugar de usar la etiqueta img, representa el svg como svg desde el principio.

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

ahora cuando renderice el archivo obtendrá svg en línea completo

nechemya ungar
fuente
0

abra el icono de svg en su editor de código y agregue una clase después de la etiqueta de ruta:

<path class'colorToChange' ...

Puede agregar clase a svg y cambiar el color de esta manera:

codepen

Hamza Jamal
fuente
-2

Si tiene acceso a JQuery, luego, extendiéndose a la respuesta de Praveen, uno puede cambiar programáticamente el color de diferentes elementos anidados dentro de SVG:

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

En find, puede mencionar diferentes elementos que deben cambiarse de color.

manyu
fuente