Modificar el color de relleno SVG cuando se sirve como Imagen de fondo


Colocando la salida SVG directamente en línea con el código de la página, puedo simplemente modificar los colores de relleno con CSS de la siguiente manera:

polygon.mystar {
    fill: blue;
}​

circle.mycircle {
    fill: green;
}

Esto funciona muy bien, sin embargo, estoy buscando una manera de modificar el atributo "fill" de un SVG cuando se está sirviendo como UNA IMAGEN DE FONDO.

html {      
    background-image: url(../img/bg.svg);
}

¿Cómo puedo cambiar los colores ahora? ¿Es posible?

Para referencia, aquí están los contenidos de mi archivo SVG externo:

<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="320px" height="100px" viewBox="0 0 320 100" enable-background="new 0 0 320 100" xml:space="preserve">
<polygon class="mystar" fill="#3CB54A" points="134.973,14.204 143.295,31.066 161.903,33.77 148.438,46.896 151.617,65.43 134.973,56.679 
    118.329,65.43 121.507,46.896 108.042,33.77 126.65,31.066 "/>
<circle class="mycircle" fill="#ED1F24" cx="202.028" cy="58.342" r="12.26"/>
</svg>
Author: chharvey, 2012-11-14

14 answers

Creo que la única manera de hacer esto es servir su svg desde algún mecanismo del lado del servidor. Simplemente cree un lado del servidor de recursos que genere su svg de acuerdo con los parámetros GET, y lo sirva en una url determinada.

Entonces solo usa esa url en tu css.

Porque como img de fondo, no es parte del DOM y no se puede manipular. Otra posibilidad sería usarlo regularmente, incrustarlo en una página de una manera normal, pero colocarlo absolutamente, hacerlo completo ancho y alto de una página y luego use la propiedad css z-index para colocarla detrás de todos los demás elementos DOM de una página.

 54
Author: tonino.j,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-27 07:40:08

Necesitaba algo similar y quería seguir con CSS. Aquí hay MENOS y SCSS mixins, así como CSS llano que puede ayudarle con esto. Desafortunadamente, su soporte para navegadores es un poco laxo. Vea a continuación los detalles sobre el soporte del navegador.

MENOS mixin:

.element-color(@color) {
  background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="@{color}" ... /></g></svg>');
}

MENOS uso:

.element-color(#fff);

SCSS mixin:

@mixin element-color($color) {
  background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="#{$color}" ... /></g></svg>');
}

Uso de SCSS:

@include element-color(#fff);

CSS:

// color: red
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="red" ... /></g></svg>');

Aquí hay más información sobre cómo incrustar el código SVG completo en su CSS file. También mencionó la compatibilidad del navegador, que es un poco demasiado pequeña para que esta sea una opción viable.

 94
Author: Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-07 20:46:22

Otro enfoque es usar máscara. A continuación, cambia el color de fondo del elemento enmascarado. Esto tiene el mismo efecto que cambiar el atributo fill del svg.

HTML:

<glyph class="star"/>
<glyph class="heart" />
<glyph class="heart" style="background-color: green"/>
<glyph class="heart" style="background-color: blue"/>

CSS:

glyph {
    display: inline-block;
    width:  24px;
    height: 24px;
}

glyph.star {
  -webkit-mask: url(star.svg) no-repeat 100% 100%;
  mask: url(star.svg) no-repeat 100% 100%;
  -webkit-mask-size: cover;
  mask-size: cover;
  background-color: yellow;
}

glyph.heart {
  -webkit-mask: url(heart.svg) no-repeat 100% 100%;
  mask: url(heart.svg) no-repeat 100% 100%;
  -webkit-mask-size: cover;
  mask-size: cover;
  background-color: red;
}

Encontrará un tutorial completo aquí: http://codepen.io/noahblon/blog/coloring-svgs-in-css-background-images (no es mío). Propone una variedad de enfoques (no limitados a la máscara).

 37
Author: widged,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-05 23:24:14

Puede usar máscaras CSS, con la propiedad 'mask', crea una máscara que se aplica a un elemento.

.icon {
    background-color: red;
    -webkit-mask-image: url(icon.svg);
    mask-image: url(icon.svg);
}

Para más ver este gran artículo: https://codepen.io/noahblon/post/coloring-svgs-in-css-background-images

 22
Author: Adel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-24 07:49:48

Es posible con Sass! Lo único que tienes que hacer es codificar tu código svg. Y esto es posible con una función auxiliar en Sass. He hecho un codepen para esto. Mira esto:

Http://codepen.io/philippkuehn/pen/zGEjxB

// choose a color

$icon-color: #F84830;


// functions to urlencode the svg string

@function str-replace($string, $search, $replace: '') {
  $index: str-index($string, $search);
  @if $index {
    @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
  }
  @return $string;
}

@function url-encode($string) {
  $map: (
    "%": "%25",
    "<": "%3C",
    ">": "%3E",
    " ": "%20",
    "!": "%21",
    "*": "%2A",
    "'": "%27",
    '"': "%22",
    "(": "%28",
    ")": "%29",
    ";": "%3B",
    ":": "%3A",
    "@": "%40",
    "&": "%26",
    "=": "%3D",
    "+": "%2B",
    "$": "%24",
    ",": "%2C",
    "/": "%2F",
    "?": "%3F",
    "#": "%23",
    "[": "%5B",
    "]": "%5D"
  );
  $new: $string;
  @each $search, $replace in $map {
    $new: str-replace($new, $search, $replace);
  }
  @return $new;
}

@function inline-svg($string) {
  @return url('data:image/svg+xml;utf8,#{url-encode($string)}');
}


// icon styles
// note the fill="' + $icon-color + '"

.icon {
  display: inline-block;
  width: 50px;
  height: 50px;
  background: inline-svg('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
   viewBox="0 0 30 30" enable-background="new 0 0 30 30" xml:space="preserve">
<path fill="' + $icon-color + '" d="M18.7,10.1c-0.6,0.7-1,1.6-0.9,2.6c0,0.7-0.6,0.8-0.9,0.3c-1.1-2.1-0.4-5.1,0.7-7.2c0.2-0.4,0-0.8-0.5-0.7
  c-5.8,0.8-9,6.4-6.4,12c0.1,0.3-0.2,0.6-0.5,0.5c-0.6-0.3-1.1-0.7-1.6-1.3c-0.2-0.3-0.4-0.5-0.6-0.8c-0.2-0.4-0.7-0.3-0.8,0.3
  c-0.5,2.5,0.3,5.3,2.1,7.1c4.4,4.5,13.9,1.7,13.4-5.1c-0.2-2.9-3.2-4.2-3.3-7.1C19.6,10,19.1,9.6,18.7,10.1z"/>
</svg>');
}
 10
Author: Philipp Kühn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-21 10:59:17

Descargue su svg como texto.

Modifique su texto svg usando javascript para cambiar el color de pintura/trazo/relleno.

Luego incruste la cadena svg modificada en línea en su css como se describe aquí.

 9
Author: jedierikb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:07

Ahora puede lograr esto en el lado del cliente de la siguiente manera:

var green = '3CB54A';
var red = 'ED1F24';
var svg = '<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="320px" height="100px" viewBox="0 0 320 100" enable-background="new 0 0 320 100" xml:space="preserve"> <polygon class="mystar" fill="#'+green+'" points="134.973,14.204 143.295,31.066 161.903,33.77 148.438,46.896 151.617,65.43 134.973,56.679 118.329,65.43 121.507,46.896 108.042,33.77 126.65,31.066 "/><circle class="mycircle" fill="#'+red+'" cx="202.028" cy="58.342" r="12.26"/></svg>';      
var encoded = window.btoa(svg);
document.body.style.background = "url(data:image/svg+xml;base64,"+encoded+")";

¡Fiddle aquí!

 8
Author: tnt-rox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-18 06:54:52

Puede almacenar el SVG en una variable. Luego manipule la cadena SVG dependiendo de sus necesidades (es decir, establecer ancho, altura, color, etc.). A continuación, utilice el resultado para establecer el fondo, por ejemplo,

$circle-icon-svg: '<svg xmlns="http://www.w3.org/2000/svg"><circle cx="10" cy="10" r="10" /></svg>';

$icon-color: #f00;
$icon-color-hover: #00f;

@function str-replace($string, $search, $replace: '') {
    $index: str-index($string, $search);

    @if $index {
        @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
    }

    @return $string;
}

@function svg-fill ($svg, $color) {
  @return str-replace($svg, '<svg', '<svg fill="#{$color}"');
}

@function svg-size ($svg, $width, $height) {
  $svg: str-replace($svg, '<svg', '<svg width="#{$width}"');
  $svg: str-replace($svg, '<svg', '<svg height="#{$height}"');

  @return $svg;
}

.icon {
  $icon-svg: svg-size($circle-icon-svg, 20, 20);

  width: 20px; height: 20px; background: url('data:image/svg+xml;utf8,#{svg-fill($icon-svg, $icon-color)}');

  &:hover {
    background: url('data:image/svg+xml;utf8,#{svg-fill($icon-svg, $icon-color-hover)}');
  }
}

También he hecho una demo, http://sassmeister.com/gist/4cf0265c5d0143a9e734 .

Este código hace algunas suposiciones sobre el SVG, por ejemplo, que el elemento <svg /> no tiene un color de relleno existente y que no se establecen las propiedades width o height. Dado que la entrada está codificada en el documento SCSS, es bastante fácil hacer cumplir estas restricciones.

No se preocupe por la duplicación de código. gzip la compresión hace que la diferencia sea insignificante.

 4
Author: Gajus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-30 12:13:57

Puede crear su propia función SCSS para esto. Agregar lo siguiente a su configuración.archivo rb.

require 'sass'
require 'cgi'

module Sass::Script::Functions

  def inline_svg_image(path, fill)
    real_path = File.join(Compass.configuration.images_path, path.value)
    svg = data(real_path)
    svg.gsub! '{color}', fill.value
    encoded_svg = CGI::escape(svg).gsub('+', '%20')
    data_url = "url('data:image/svg+xml;charset=utf-8," + encoded_svg + "')"
    Sass::Script::String.new(data_url)
  end

private

  def data(real_path)
    if File.readable?(real_path)
      File.open(real_path, "rb") {|io| io.read}
    else
      raise Compass::Error, "File not found or cannot be read: #{real_path}"
    end
  end

end

Entonces puedes usarlo en tu CSS:

.icon {
  background-image: inline-svg-image('icons/icon.svg', '#555');
}

Tendrá que editar sus archivos SVG y reemplazar cualquier atributo de relleno en el marcado con fill="{color}"

La ruta del icono siempre es relativa al parámetro images_dir en la misma configuración.archivo rb.

Similar a algunas de las otras soluciones, pero esto es bastante limpio y mantiene sus archivos SCSS ordenados!

 3
Author: Lomax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-16 21:37:32
 .icon { 
  width: 48px;
  height: 48px;
  display: inline-block;
  background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/18515/heart.svg) no-repeat 50% 50%; 
  background-size: cover;
}

.icon-orange { 
  -webkit-filter: hue-rotate(40deg) saturate(0.5) brightness(390%) saturate(4); 
  filter: hue-rotate(40deg) saturate(0.5) brightness(390%) saturate(4); 
}

.icon-yellow {
  -webkit-filter: hue-rotate(70deg) saturate(100);
  filter: hue-rotate(70deg) saturate(100);
}

Codeben artículo y demo

 3
Author: Elbaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-11 08:20:26

Tarde para el show aquí, PERO, pude agregar un color de relleno al polígono SVG, si puede editar directamente el código SVG, por ejemplo, el siguiente svg renderiza rojo, en lugar del negro predeterminado. No he probado fuera de Chrome aunque:

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


        fill="red"


        fill-rule="evenodd" clip-rule="evenodd" points="452.5,233.85 452.5,264.55 110.15,264.2 250.05,390.3 229.3,413.35 
47.5,250.7 229.3,86.7 250.05,109.75 112.5,233.5 "/>
</svg>
 1
Author: Eleanor Zimmermann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-09 00:29:05

En algunas situaciones (muy específicas) esto podría lograrse usando un filtro . Por ejemplo, puede cambiar una imagen SVG azul a púrpura girando el tono 45 grados usando filter: hue-rotate(45deg);. El soporte del navegador es mínimo, pero sigue siendo una técnica interesante.

Demo

 1
Author: Michaël van de Weerd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-11 13:59:28

Este es mi método favorito, pero el soporte de su navegador debe ser muy progresivo. Con la propiedad mask se crea una máscara que se aplica a un elemento. En todas partes la máscara es opaca, o sólida, la imagen subyacente muestra a través. Cuando es transparente, la imagen subyacente está enmascarada u oculta. La sintaxis para una imagen de máscara CSS es similar a la imagen de fondo. mira el codepenmask

 -1
Author: Mebin Benny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-03 05:52:15

Un montón de IFs, pero si su SVG codificado pre base64 comienza:

<svg fill="#000000

Entonces comenzará la cadena codificada en base64:

PHN2ZyBmaWxsPSIjMDAwMDAw

Si se inicia la cadena precodificada:

<svg fill="#bfa76e

Entonces esto codifica para:

PHN2ZyBmaWxsPSIjYmZhNzZl

Ambas cadenas codificadas comienzan de la misma manera:

PHN2ZyBmaWxsPSIj

La peculiaridad de la codificación base64 es que cada 3 caracteres de entrada se convierten en 4 caracteres de salida. Con el SVG comenzando así, el color de relleno hexadecimal de 6 caracteres comienza exactamente en un bloque de codificación 'límite'. Por lo tanto, puede hacer fácilmente un reemplazo JS entre navegadores:

output = input.replace(/MDAwMDAw/, "YmZhNzZl");

Pero la respuesta de tnt-rox anterior es la manera de seguir adelante.

 -2
Author: A2D,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-17 11:52:53