Modifier SVG fill color lorsqu'il est servi comme arrière-plan-Image

placer la sortie SVG directement en ligne avec le code de la page je suis en mesure de simplement modifier remplir les couleurs avec CSS comme suit:

polygon.mystar {
    fill: blue;
}​

circle.mycircle {
    fill: green;
}

cela fonctionne très bien, mais je cherche un moyen de modifier l'attribut" fill " D'un SVG lorsqu'il est utilisé comme image D'arrière-plan.

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

Comment changer les couleurs maintenant? Est-il même possible?

pour référence, voici le contenu de mon fichier SVG externe:

<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>
156
demandé sur chharvey 2012-11-14 00:02:43

14 réponses

je pense que la seule façon pour vous de faire cela est de servir votre svg à partir d'un mécanisme côté serveur. Il suffit de créer un côté du serveur de ressources qui affiche votre svg selon les paramètres GET, et vous le servez sur une certaine url.

alors vous n'avez qu'à utiliser cette url dans votre css.

parce que comme IMG de fond, il ne fait pas partie du DOM et vous ne pouvez pas le manipuler. Une autre possibilité serait de l'utiliser régulièrement, l'incorporer dans une page d'une manière normale, mais positionnez-le absolument, faites-le plein Largeur & Hauteur d'une page et puis utilisez la propriété CSS z-index pour le mettre derrière tous les autres éléments DOM sur une page.

54
répondu tonino.j 2015-10-27 07:40:08

j'avais besoin de quelque chose de similaire et je voulais rester avec CSS. Voici moins et SCSS mixins ainsi que CSS simple qui peuvent vous aider avec cela. Malheureusement, son soutien de navigateur est un peu lax. Voir ci-dessous pour plus de détails sur le support du navigateur.

moins mixin:

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

moins d'utilisation:

.element-color(#fff);

SCSS mixin:

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

utilisation SCSS:

@include element-color(#fff);

CSS:

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

voici plus d'info sur l'intégration du code SVG complet dans votre fichier CSS. Il a également mentionné la compatibilité du navigateur qui est un peu trop petite pour que ce soit une option viable.

94
répondu Ryan 2017-07-07 20:46:22

encore une autre approche est d'utiliser le masque. Vous changez ensuite la couleur de fond de l'élément masqué. Cela a le même effet que de changer l'attribut fill de la 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;
}

, Vous trouverez un tutoriel complet ici: http://codepen.io/noahblon/blog/coloring-svgs-in-css-background-images (pas le mien). Il propose une variété d'approches (non limitée masquer.)

37
répondu widged 2015-08-05 23:24:14

vous pouvez utiliser des masques CSS, avec la propriété 'mask', vous créez un masque qui est appliqué à un élément.

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

pour plus voir ce grand article: https://codepen.io/noahblon/post/coloring-svgs-in-css-background-images

22
répondu Adel 2017-10-24 07:49:48

c'est possible avec Sass! La seule chose à faire est d'encoder votre code svg. Et c'est possible avec une fonction helper dans Sass. J'ai fait un codepen pour cela. Regardez ça:

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
répondu Philipp Kühn 2015-06-21 10:59:17

Téléchargez votre svg sous forme de texte.

modifiez votre texte svg en utilisant javascript pour changer la couleur[s].

intègre alors la chaîne svg modifiée dans votre css comme décrit ici .

9
répondu jedierikb 2017-05-23 12:10:07

Maintenant vous pouvez réaliser ceci du côté du client comme ceci:

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+")";

Violon ici!

8
répondu tnt-rox 2014-08-18 06:54:52

vous pouvez stocker la SVG dans une variable. Puis manipulez la chaîne SVG en fonction de vos besoins (i.e., définissez la largeur, la hauteur, la couleur, etc.). Ensuite, utilisez le résultat pour définir le fond, par exemple

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

j'ai aussi fait une démo, http://sassmeister.com/gist/4cf0265c5d0143a9e734 .

ce code fait quelques hypothèses au sujet de la SVG, par exemple que l'élément <svg /> n'a pas de couleur de remplissage existante et que aucune propriété de largeur ou de hauteur n'est définie. Comme l'entrée est codée en dur dans le document SCSS, il est assez facile d'appliquer ces contraintes.

ne vous souciez pas de la duplication du code. compression rend la différence négligeable.

4
répondu Gajus 2015-10-30 12:13:57

vous pouvez créer votre propre fonction SCSS pour cela. Ajouter ce qui suit à votre configuration.dossier 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

alors vous pouvez l'utiliser dans votre CSS:

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

vous devrez éditer vos fichiers SVG et remplacer tout attribut de fill dans le markup par fill= "{color} "

le chemin de l'icône est toujours relatif à votre paramètre images_dir dans la même configuration.dossier rb.

similaire à certains des d'autres solutions, mais c'est assez propre et garde vos fichiers SCSS bien rangés!

3
répondu Lomax 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);
}

article codeben et démo

3
répondu Elbaz 2017-04-11 08:20:26

en retard sur le show ici, mais, j'ai pu ajouter une couleur de remplissage au polygone SVG, si vous êtes capable d'éditer directement le code SVG, ainsi par exemple le SVG suivant rend rouge, au lieu de noir par défaut. Je n'ai pas testé en dehors de Chrome cependant:

<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
répondu Eleanor Zimmermann 2015-04-09 00:29:05

C'est ma méthode préférée, mais votre navigateur doit être très progressive. Avec la propriété mask vous créez un masque qui est appliqué à un élément. Partout où le masque est opaque, ou solide, l'image sous-jacente apparaît à travers. Lorsqu'il est transparent, l'image sous-jacente est masquée, ou cachés. La syntaxe pour un masque CSS-image est similaire à background-image. regardez le codepen mask

-1
répondu Mebin Benny 2016-11-03 05:52:15

beaucoup de IFs, mais si votre SVG encodé pré base64 commence:

<svg fill="#000000

puis la chaîne encodée base64 commencera:

PHN2ZyBmaWxsPSIjMDAwMDAw

si la chaîne pré-encodée commence:

<svg fill="#bfa76e

alors ceci code à:

PHN2ZyBmaWxsPSIjYmZhNzZl

les deux chaînes encodées commencent de la même façon:

PHN2ZyBmaWxsPSIj

le truc de l'encodage base64 est que tous les 3 caractères d'entrée deviennent 4 caractères de sortie caractère. Avec la SVG commençant comme ceci, la couleur de remplissage hexadécimal de 6 caractères commence exactement sur un bloc d'encodage 'boundary'. Par conséquent, vous pouvez facilement faire un cross-browser js remplacer:

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

mais la réponse de tnt-rox ci-dessus est la façon d'aller de l'avant.

-2
répondu A2D 2016-02-17 11:52:53