img src SVG changer les styles avec CSS

375

html

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

css

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

Le svg ci-dessus se charge et est natif, fill: #fffmais lorsque j'utilise ce qui précède csspour essayer de le changer en noir, il ne change pas, c'est ma première fois à jouer avec SVG et je ne sais pas pourquoi cela ne fonctionne pas.

ngplayground
la source
26
Vous ne pouvez pas affecter les images SVG comme ça ... uniquement des éléments SVG en ligne
Paulie_D
Vérifiez ma réponse ici pour utiliser le contenu de SVG et CSS. stackoverflow.com/questions/11978995/…
Benjamin

Réponses:

153

Si votre objectif est simplement de changer la couleur du logo et que vous n'avez pas nécessairement besoin d'utiliser CSS, n'utilisez pas javascript ou jquery comme cela a été suggéré par certaines réponses précédentes.

Pour répondre précisément à la question d'origine, il suffit:

  1. Ouvrez votre logo.svgdans un éditeur de texte.

  2. le chercher fill: #fffet le remplacer parfill: #000

Par exemple, votre logo.svgpourrait ressembler à ceci lorsqu'il est ouvert dans un éditeur de texte:

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

... changez simplement le remplissage et enregistrez.

Rowe Morehouse
la source
6
... et s'il n'y a pas de "remplissage", vous pouvez simplement l'ajouter au pathou aux circleéléments comme <path fill="#777777" d="m129.774,74.409c-5.523,....
SaeX
1
que faire si mon logo a une couleur sur l'en-tête et une autre couleur sur le pied de page?
rubens.lopes
. @ ruben.lopes deux fichiers différents, ou deux inserts différents seraient les plus simples
Rowe Morehouse
11
vous pouvez également utiliser le fill="currentColor"puis utiliser l' colorélément sur l'élément parent css-tricks.com/cascading-svg-fill-color
Serge
10
C'est évidemment possible et ce n'est pas vraiment une réponse utile.
Timmmm
101

Vous pouvez définir votre SVG comme masque. De cette façon, définir une couleur d'arrière-plan agirait comme votre couleur de remplissage.

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

Veuillez vérifier si votre navigateur prend en charge cette fonctionnalité: https://caniuse.com/#search=mask

André Kuhlmann
la source
3
Donc pour tout sauf site Web interne inutilisable.
Henrik Vendelbo
9
89% de support mondial au 29 mai 2016.
Gajus
1
Il s'agit d'une solution étonnante pour des situations comme celle décrite ici , où l'utilisation d'autre chose que les uris de données dans CSS est un peu pénible. Merci!
Gark Garcia
3
ça ne fonctionne pas. il dit que maskc'est un invalid property value. je teste cela en chrome.
Eren555
1
@MadMac J'utilise la même version de Chrome, mais je n'ai pas pu reproduire ce comportement. Est-ce le JSFiddle que vous avez essayé ou votre code?
André Kuhlmann
79

Essayez du CSS pur:

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

plus d'informations dans cet article https://blog.union.io/code/2017/08/10/img-svg-fill/

Feri
la source
J'obtenais une couleur différente sur Edge que sur d'autres navigateurs avec l'une de mes tentatives récemment.
Julix
4
Cela fonctionne dans la plupart des navigateurs mais j'ai eu quelques problèmes avec le navigateur IOS-Safari.
Simon Ludwig
31

2018: Si vous voulez une couleur dynamique, ne voulez pas utiliser le javascript et ne voulez pas un SVG en ligne, utilisez une variable CSS. Fonctionne dans Chrome, Firefox et Safari. modifier: et Edge

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

Dans votre SVG, remplacez toutes les instances de style="fill: #000"par style="fill: var(--color_fill)".

Nord Américain
la source
1
Quel est le support du navigateur pour cela
Kevin Goedecke
@KevinGoedecke Chrome, Firefox, Safari et Edge
nord-américain
4
Semble obsolète dans SVG 2
vsync
5
@northamerican - les liens vers d'autres réponses de stackoverflow en tant que "preuves" ne sont pas pertinents. n'importe qui peut écrire n'importe quoi sur cette plateforme. 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
Il semble que xlink:hrefsoit déconseillé en faveur de href. Cela peut donc toujours fonctionner.
Benjamin Intal
20

Vous devrez d'abord injecter le SVG dans le DOM HTML.

Il existe une bibliothèque open source appelée SVGInject qui le fait pour vous. Il utilise l' onloadattribut pour déclencher l'injection.

Voici un exemple minimal utilisant SVGInject:

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

Une fois l'image chargée onload="SVGInject(this), l' <img>élément déclenchera l'injection et l' élément sera remplacé par le contenu du fichier SVG fourni dans l' srcattribut.

Il résout plusieurs problèmes avec l'injection SVG:

  1. Les SVG peuvent être masqués jusqu'à la fin de l'injection. Ceci est important si un style est déjà appliqué pendant le temps de chargement, ce qui provoquerait sinon un bref "flash de contenu sans style".

  2. Les <img>éléments s'injectent automatiquement. Si vous ajoutez des SVG dynamiquement, vous n'avez pas à vous soucier d'appeler à nouveau la fonction d'injection.

  3. Une chaîne aléatoire est ajoutée à chaque ID dans le SVG pour éviter d'avoir le même ID plusieurs fois dans le document si un SVG est injecté plusieurs fois.

SVGInject est Javascript simple et fonctionne avec tous les navigateurs qui prennent en charge SVG.

Avertissement: je suis le co-auteur de SVGInject

Waruyama
la source
3
C'est la réponse la plus simple. Je l'ai testé dans Chrome, Firefox et Edge et cela fonctionne parfaitement.
Sébastien Lorion
15

La réponse de @Praveen est solide.

Je ne pouvais pas le faire répondre dans mon travail, j'ai donc fait une fonction de survol jquery pour cela.

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
la source
1
cela ne fonctionnerait-il que si le SVG était en ligne pour commencer?
Daniel Thompson
Oui, mais si vous travaillez avec de nombreux fichiers SVG ou si vous les mettez à jour régulièrement, c'est difficile à gérer.
Matt Wujek
15

Pourquoi ne pas créer une police Web avec votre image ou vos images SVG, importer la police Web dans le CSS et ensuite simplement changer la couleur du glyphe en utilisant l'attribut de couleur CSS? Pas de javascript nécessaire

gringo
la source
5
Si votre svg comporte plusieurs éléments de couleurs différentes, cette solution devient très hacky (plusieurs éléments interposés).
kakaja
1
@kakaja Ceci est une solution uniquement pour les images vectorielles qui contiennent 1 couleur. voir la réponse de bpulecio pour plus de détails
gringo
1
Parce que l'icône n'est pas du texte. Les polices sont destinées au texte. Les SVG sont pour les icônes.
Lazar Ljubenović
2
@ LazarLjubenović - techniquement, le texte est composé de caractères qui sont des symboles, et les icônes sont également des symboles, c'est pourquoi beaucoup n'ont pas de problème à utiliser les polices d'icônes. c'est comme créer un "autre" langage textuel. Le mandarin utilise des "icônes" et pas des lettres aussi, il n'est pas rare dans l'humanité d'utiliser des icônes comme "texte"
vsync
1
bien que cela semble être une solution intéressante, je recommande vraiment d'élaborer la réponse en quelque chose de plus comme "comment" au lieu de "pourquoi pas"
YakovL
15

Cette réponse est basée sur la réponse https://stackoverflow.com/a/24933495/3890888 mais avec une version JavaScript simple du script utilisé.

Vous devez faire du SVG un SVG en ligne . Vous pouvez utiliser ce script, en ajoutant une classe svgà l'image:

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

    });

});

Et puis, maintenant si vous le faites:

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

Ou peut-être:

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

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

Seb3736
la source
1
Grands travaux. en outre, si notre page contient plusieurs fichiers SVG, nous devrons mettre le bloc d'extraction dans l'IIFE.
Sandeep Sharma
1
Génial! Fonctionne bien avec ES6. Si vous ne vous souciez pas d'IE 9, vous pouvez même utiliser: parser.parseFromString(text, "image/svg+xml");
ChristoKiwi
Ne fonctionne pas dans une UIWebView sur iOS 9.3.5. Je pense que cela pourrait être dû à l'utilisation de fetchce qui a été ajouté à Safari dans 10.1 ( developer.mozilla.org/en-US/docs/Web/API/Fetch_API ). La version jQuery ci-dessus fonctionne.
Maria-Ines Carrera
7

Utilisez des filtres pour vous transformer en n'importe quelle couleur.

J'ai récemment trouvé cette solution et j'espère que quelqu'un pourra l'utiliser. Étant donné que la solution utilise des filtres, elle peut être utilisée avec tout type d'image. Pas seulement svg.

Si vous avez une image monochrome dont vous voulez juste changer la couleur, vous pouvez le faire à l'aide de certains filtres. Cela fonctionne bien sûr sur les images multicolores, mais vous ne pouvez pas cibler une couleur spécifique. Seule l'image entière.

Les filtres provenaient du script proposé dans Comment transformer le noir en n'importe quelle couleur en utilisant uniquement des filtres CSS Si vous voulez changer le blanc en n'importe quelle couleur, vous pouvez ajuster la valeur d'inversion dans chaque filtre.

.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
la source
5

Si vous ne faites que basculer l'image entre la couleur réelle et le noir et blanc, vous pouvez définir un sélecteur comme suit:

{filtre: aucun;}

et un autre comme:

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

Pour développer la réponse @gringo, la méthode Javascript décrite dans d'autres réponses fonctionne, mais nécessite que l'utilisateur télécharge des fichiers image inutiles, et IMO, il gonfle votre code.

Je pense qu'une meilleure approche serait de migrer tous les graphiques vectoriels 1 couleur vers un fichier webfont. J'ai utilisé Fort Awesome dans le passé, et cela fonctionne très bien pour combiner vos icônes / images personnalisées au format SVG, ainsi que toutes les icônes tierces que vous utilisez (Font Awesome, icônes Bootstrap, etc.) dans un seul fichier de police Web l'utilisateur doit télécharger. Vous pouvez également le personnaliser, de sorte que vous n'incluez que les icônes tierces que vous utilisez. Cela réduit le nombre de demandes que la page doit faire et vous avez un poids global de page, surtout si vous incluez déjà des bibliothèques d'icônes tierces.

Si vous préférez une option plus orientée vers les développeurs, vous pouvez utiliser Google "npm svg webfont" et utiliser l'un des modules de nœuds les plus appropriés pour votre environnement.

Une fois que vous avez fait l'une de ces deux options, vous pouvez facilement changer la couleur via CSS et, très probablement, vous avez accéléré votre site dans le processus.

bpulecio
la source
Vous devriez essayer les sprites SVG. D'après mon expérience, les polices Web ont des problèmes aléatoires entre les versions du navigateur. Essayez ceci: fontastic.me - mais utilisez les versions de sprite SVG - et voyez ce que vous en pensez. :)
sheriffderek
3

Facile..

Vous pouvez utiliser ce code:

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

Spécifiez d'abord le chemin de svg puis écrivez son ID, dans ce cas "Capa_1". Vous pouvez obtenir l'ID de svg en l'ouvrant dans n'importe quel éditeur.

En CSS:

.logo {
  fill: red;
}
Hamza Jamal
la source
kabrice, Vous pouvez utiliser ce code codepen.io/hmzajmal/pen/ZEGvWYa
Hamza Jamal
2

Le problème principal dans votre cas est que vous importez le svg à partir d'une <img>balise qui masquera la structure SVG.

Vous devez utiliser la <svg>balise en conjonction avec le <use>pour obtenir l'effet souhaité. Pour le faire fonctionner, vous devez donner un idau chemin que vous souhaitez utiliser dans le fichier SVG <path id='myName'...>pour pouvoir ensuite les récupérer à partir de la <use xlink:href="#myName"/>balise. Essayez le découpé ci-dessous.

Notez que vous pouvez mettre n'importe quelle URL avant le fragment #si vous souhaitez charger le SVG à partir d'une source externe (et ne pas l'intégrer dans votre HTML). En outre, vous ne spécifiez généralement pas le remplissage dans le CSS. Il est préférable d'envisager l'utilisation fill:"currentColor"dans le SVG lui-même. La valeur de couleur CSS de l'élément correspondant sera alors utilisée en place.

Flavien Volken
la source
2

Puisque SVG est essentiellement du code, vous avez juste besoin de contenu. J'ai utilisé PHP pour obtenir du contenu, mais vous pouvez utiliser ce que vous voulez.

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

Ensuite, j'ai imprimé le contenu "tel quel" dans un conteneur div

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

Pour définir enfin la règle sur les enfants SVG du conteneur sur CSS

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

J'ai obtenu ces résultats avec une icône matérielle SVG:

Mozilla Firefox 59.0.2 (64 bits) Linux

entrez la description de l'image ici

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

entrez la description de l'image ici

Opera 53.0.2907.37 Linux

entrez la description de l'image ici

Benjamin
la source
Je ne peux pas voter contre, mais je vous prie de ne jamais faire cela.
ponceuse
5
Les raisons? Des alternatives?
Benjamin
Ma raison pour ne pas le faire est que cela empêche le navigateur de mettre en cache le SVG. L'alternative est d'utiliser un injecteur SVG mentionné dans quelques autres réponses ici. Le fichier SVG sera toujours mis en cache par le navigateur, et le SVG injecté peut toujours être stylisé avec CSS. Mais je ne vous vote pas.
Sơn Trần-Nguyễn
Je comprends, mais de toute façon, le cache n'est pas mentionné. La meilleure réponse est un code JavaScript qui peut être rechargé (ou non) à chaque fois que la manipulation expire l'en-tête ou force un hachage après le lien du nom de fichier.
Benjamin
2

Cela pourrait être utile pour les personnes utilisant PHPen combinaison avec des .svgimages qu'ils souhaitent manipuler avec CSS.

Vous ne pouvez pas remplacer les propriétés à l'intérieur d'une balise img avec CSS. Mais lorsque le code source svg est intégré dans le HTML, vous le pouvez sûrement. J'aime résoudre ce problème avec une require_oncefonction où j'inclus un .svg.phpfichier. C'est comme importer une image mais vous pouvez toujours écraser les styles avec CSS!

Incluez d'abord le fichier svg:

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

Et il comprend cette icône par exemple:

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

Maintenant, nous pouvons facilement changer la couleur de remplissage comme ceci avec CSS:

svg path {
  fill: blue;
}

J'ai d'abord essayé de résoudre ce problème avec file_get_contents()mais la solution ci-dessus est beaucoup plus rapide.

Floris
la source
0

Sachez que c'est une vieille question mais récemment nous sommes tombés sur le même problème, et nous l'avons résolu du côté serveur. C'est une réponse spécifique à PHP mais je suis certain que d'autres envs ont quelque chose de similaire. au lieu d'utiliser la balise img, vous rendez le svg en svg dès le départ.

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

maintenant, lorsque vous rendrez le fichier, vous obtiendrez un svg en ligne complet

nechemya ungar
la source
0

ouvrez l'icône svg dans votre éditeur de code et ajoutez une classe après la balise path:

<path class'colorToChange' ...

Vous pouvez ajouter une classe à svg et changer la couleur comme ceci:

codepen

Hamza Jamal
la source
-2

Si vous avez accès à JQuery, puis en étendant la réponse de Praveen, vous pouvez changer par programme la couleur des différents éléments imbriqués dans SVG en:

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

Dans find, vous pouvez mentionner différents éléments qui doivent être modifiés en couleur.

manyu
la source