¿Cómo cambiar el color de un elemento svg?


352

Quiero usar esta técnica http://css-tricks.com/svg-fallbacks/ y cambiar el color de svg, pero hasta ahora no he podido hacerlo. Puse esto en el CSS pero mi imagen siempre es negra, pase lo que pase. Mi 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>


No soy un experto en svg, pero ¿has intentado cambiar el relleno a color de fondo?
Meg

@Megan en svg background-color se especifica con la propiedad 'fill' y el borde con 'stroke' (como lo haría en Illustrator). w3.org/TR/SVG/propidx.html
Barbara

44
El CSS de su documento HTML no se aplicará a los elementos SVG dentro de <img />
pawel

1
Esto es posible ahora. Respuesta simple y funcional aquí: stackoverflow.com/a/53336754/467240
mtyson

Respuestas:


189

No puede cambiar el color de una imagen de esa manera. Si carga SVG como imagen, no puede cambiar cómo se muestra usando CSS o Javascript en el navegador.

Si desea cambiar su imagen SVG, lo que tienes que cargarlo usando <object>, <iframe>o el uso <svg>en línea.

Si desea utilizar las técnicas en la página, necesita la biblioteca Modernizr, donde puede verificar la compatibilidad con SVG y mostrar condicionalmente o no una imagen alternativa. Luego puede alinear su SVG y aplicar los estilos que necesita.

Ver :

Puede alinear su SVG, etiquetar su imagen alternativa con un nombre de clase ( 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" />

Y en CSS use la no-svgclase de Modernizr (CDN: http://ajax.aspnetcdn.com/ajax/modernizr/modernizr-2.7.2.js ) para verificar la compatibilidad con SVG. Si no hay soporte SVG, el bloque SVG se ignorará y se mostrará la imagen; de lo contrario, la imagen se eliminará del árbol DOM ( display: none):

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

Luego puede cambiar el color de su elemento en línea:

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

55
No puede objectdiseñar SVG incrustados desde el documento de alojamiento.
Javier Rey

1
@JavierRey puede inyectar el estilo en el contenido de la etiqueta del objeto a través de JavaScript Pero tiene razón en que no se aplica si solo lo agrega a la hoja de estilo del documento de alojamiento.
Robert Longson

2
Estoy usando la solución de @ manish-menaria y funciona perfectamente.
Ryan Ellis

1
La respuesta aceptada debe cambiarse a: stackoverflow.com/a/53336754/467240
mtyson

377

Respuesta 2020

El filtro CSS funciona en todos los navegadores actuales

Para cambiar cualquier color SVG

  1. Agregue la imagen SVG usando una <img>etiqueta.
<img src="dotted-arrow.svg" class="filter-green"/>
  1. Para filtrar a un color específico, use el siguiente Codepen (haga clic aquí para abrir codepen) para convertir un código de color hexadecimal en un filtro CSS:

Por ejemplo, la salida para #00EE00es

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

55
Esto viene con la advertencia habitual de no ser compatible con versiones anteriores del navegador: developer.mozilla.org/en-US/docs/Web/CSS/…
Kevin Wang

17
Como se señaló en CodePen, si su SVG no es negro (el mío era gris), agregar brightness(0) saturate(100%)al comienzo de la lista de filtros primero lo convertirá en 100% negro, lo que permite que los otros filtros lo cambien al color correcto.
jdunning

2
Además, hay muchos antecedentes fascinantes sobre la solución en esta pregunta de StackOverflow que informó a CodePen.
jdunning

3
Mi chico. El soporte parece aceptable caniuse.com/#feat=css-filters .
Sam Doidge, el

funciona muy bien, usé este codepen no afiliado para poner mi hexadecimal en un filtro: codepen.io/sosuke/pen/Pjoqqp
WEBjuju

220

Para cambiar el color de cualquier SVG, puede cambiar directamente el código svg abriendo el archivo svg en cualquier editor de texto . El código puede verse como el siguiente código

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

Se puede observar que hay algunas etiquetas XML como camino, círculo, polígono, etc . Allí puede agregar su propio color con la ayuda del atributo de estilo . Mira el siguiente ejemplo

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

Agregue el atributo de estilo a todas las etiquetas para que pueda obtener su SVG del color requerido


48
¿Por qué no solo usar atributos fillcomo este fill = "#AB7C94":? No estoy seguro de por qué stylese necesita el atributo
bg17aw

44
Hola Daniel, si funciona. No sabía que el relleno se puede usar como un atributo. Lo siento por no notar tu comentario tanto tiempo @ bg17aw
sushant047


21

Solo SVG con información de ruta . no puede hacer eso a la imagen ... como la ruta puede cambiar el trazo y completar la información y ya está. como ilustrador

entonces: a través de CSS puede sobrescribir el fillvalor de la ruta

path { fill: orange; }

pero si desea una forma más flexible ya que desea cambiarlo con un texto cuando tiene algún efecto flotante ... 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

la forma más fácil sería crear una fuente a partir del SVG utilizando un servicio como https://icomoon.io/app/#/select o similar . cargue su SVG, haga clic en "generar fuente", incluya archivos de fuente y css en su lado y simplemente utilícelo y déle estilo como cualquier otro texto. Siempre lo uso así porque hace que el estilo sea mucho más fácil.

EDITAR: Como se mencionó en el artículo comentado por @ CodeMouse92, las fuentes de iconos alteran los lectores de pantalla (y posiblemente son malas para el SEO). Así que más bien se adhieren a los SVG.


55
También arruina los lectores de pantalla. Ver "Death to Icon Fonts" por Seren Davies
CodeMouse92

7

La máscara SVG en un elemento de cuadro con un color de fondo dará como resultado:

.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: las máscaras SVG no son compatibles con los navegadores Internet Explorer


1
Muchas gracias, @vsync, este es el mejor truco para lo que necesito.
Vixson

6

Puede cambiar el color SVG con css si usa algunos trucos. Escribí un pequeño guión para eso.

  • ir a través de una lista de elementos que tienen una imagen svg
  • cargar el archivo svg como xml
  • buscar solo parte de svg
  • cambiar el color del camino
  • reemplace src con el svg modificado como imagen en línea
$('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')));
  });

});

el código anterior podría no funcionar correctamente, lo he implementado para elementos con una imagen de fondo svg que funciona de manera similar a esto. Pero de todos modos, debe modificar este script para que se ajuste a su caso. Espero que haya ayudado.


Por cierto: si eres un desarrollador de RoR, puedes agregar un nuevo método para el precompilador sass que también puede hacer el trabajo. Esto es mucho mejor porque tendrá la imagen coloreada correcta codificada en base64 en su archivo css compilado. ¡Ya no se necesita JS! Tal vez podría proporcionar el código que he escrito, tengo que hablar con el CTO.
cydoc

2
+1 por proporcionar una solución, en lugar de decir que no se puede hacer. Esta respuesta también es relevante: stackoverflow.com/questions/11978995/…
claytronicon

6

Apunte la ruta dentro del svg:

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

Puedes hacerlo en línea, como:

<path fill="#ccc">

O

svg{
   path{
        fill: #ccc


2

Si desea hacer esto en un svg en línea que es, por ejemplo, una imagen de fondo en su 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");

por supuesto, reemplace el ... con su código de imagen en línea


2

Por ejemplo, en tu 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>");

Esto solo funciona si incluye el archivo SVG en línea en el HTML. He editado tu respuesta para aclarar esto.
Flimm

0

En realidad, hay una solución bastante más flexible para este problema: escribir un componente web que parcheará SVG como texto en tiempo de ejecución. También publicado en gist con un enlace a JSFiddle

👍 filtro: invertir (42%) sepia (93%) saturar (1352%) brillo de rotación de tono (87deg) (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

La forma más corta compatible con Bootstrap, sin 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;
}

y úsalo como:

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

-1

Abra su imagen usando un navegador, haga clic derecho en la imagen, haga clic en ver la fuente de la página y verá la etiqueta svg de la imagen. Copie y pegue en su html, luego cambie el relleno al color de su elección


La respuesta aceptada ya sugiere alinear y luego configurar el color como la solución.
Robert Longson

-1

Simplemente agregue fill: "desiredColor" en la etiqueta svg de la imagen: ejemplo:

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

Esa es básicamente la misma sugerencia que esta respuesta o esta
Robert Longson,

esas respuestas han mencionado completar la etiqueta de ruta, funcionó para mí en la etiqueta svg, por lo tanto, lo
publiqué
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.