466 votes

Comment changer la couleur d'une image SVG à l'aide de CSS (remplacement d'image SVG par jQuery) ?

Il s'agit d'une auto-questionnaire d'un morceau de code pratique que j'ai créé.

Actuellement, il n'existe pas de moyen simple d'intégrer une image SVG et d'avoir ensuite accès aux éléments SVG via CSS. Il existe plusieurs méthodes permettant d'utiliser des cadres JS SVG, mais elles sont trop compliquées si tout ce que vous faites est de créer une simple icône avec un état de renversement.

Voici donc ce que j'ai mis au point, qui, à mon avis, est de loin le moyen le plus simple d'utiliser des fichiers SVG sur un site web. Son concept s'inspire des premières méthodes de remplacement du texte par l'image, mais pour autant que je sache, cela n'a jamais été fait pour les SVG.

C'est la question :

Comment intégrer un SVG et changer sa couleur en CSS sans utiliser un framework JS-SVG ?

2 votes

Malheureusement, la balise img ne fonctionne pas avec les fichiers svg dans IE, il faut donc en tenir compte. IE reconnaît les balises embed. Quoi qu'il en soit, bon travail !

3 votes

Pour les svg, vous devez utiliser la propriété css "fill". Pour les images, il est approprié d'utiliser "filter". En fait, "Filter" fonctionne pour les deux, mais il est inutile de faire tout ce travail pour un graphique vectoriel.

558voto

Drew Baker Points 2582

Tout d'abord, utilisez une balise IMG dans votre HTML pour intégrer un graphique SVG. J'ai utilisé Adobe Illustrator pour réaliser le graphique.

<img id="facebook-logo" class="svg social-link" src="/images/logo-facebook.svg"/>

C'est exactement comme pour l'intégration d'une image normale. Notez que vous devez définir l'IMG pour avoir une classe de svg. La classe "social-link" n'est utilisée qu'à titre d'exemple. L'ID n'est pas obligatoire, mais il est utile.

Utilisez ensuite ce code jQuery (dans un fichier séparé ou en ligne dans le HEAD).

    /**
     * Replace all SVG images with inline SVG
     */
        jQuery('img.svg').each(function(){
            var $img = jQuery(this);
            var imgID = $img.attr('id');
            var imgClass = $img.attr('class');
            var imgURL = $img.attr('src');

            jQuery.get(imgURL, function(data) {
                // Get the SVG tag, ignore the rest
                var $svg = jQuery(data).find('svg');

                // Add replaced image's ID to the new SVG
                if(typeof imgID !== 'undefined') {
                    $svg = $svg.attr('id', imgID);
                }
                // Add replaced image's classes to the new SVG
                if(typeof imgClass !== 'undefined') {
                    $svg = $svg.attr('class', imgClass+' replaced-svg');
                }

                // Remove any invalid XML tags as per http://validator.w3.org
                $svg = $svg.removeAttr('xmlns:a');

                // Replace image with new SVG
                $img.replaceWith($svg);

            }, 'xml');

        });

Le code ci-dessus recherche tous les IMG avec la classe 'svg' et les remplace par le SVG en ligne du fichier lié. L'avantage majeur est qu'il vous permet d'utiliser le CSS pour changer la couleur du SVG, comme suit :

svg:hover path {
    fill: red;
}

Le code jQuery que j'ai écrit porte également sur l'ID et les classes des images originales. Donc ce CSS fonctionne aussi :

#facebook-logo:hover path {
    fill: red;
}

Ou :

.social-link:hover path {
    fill: red;
}

Vous pouvez voir un exemple de son fonctionnement ici : http://labs.funkhausdesign.com/examples/img-svg/img-to-svg.html

Nous avons une version plus compliquée qui inclut la mise en cache ici : https://github.com/funkhaus/style-guide/blob/master/template/js/site.js#L32-L90

0 votes

Merci ! Il donne quelques erreurs étranges sur IE9. Faites-moi savoir si vous avez des idées sur la façon de corriger cela.

0 votes

C'est génial ! Je cherchais un moyen de garder le balisage propre, tout en permettant l'accès aux "entrailles" du svg pour une utilisation en CSS. Cela devrait fonctionner, mais je reçois une erreur avec le JS : "XMLHttpRequest cannot load file:///H:/svg/test/test.svg. Origin null n'est pas autorisé par Access-Control-Allow-Origin". Une idée ?

0 votes

Je pense que c'est parce que vous l'exécutez localement et que vous rencontrez un problème de domaine croisé. Mettez-le sur un serveur et il devrait fonctionner.

59voto

Style

svg path {
    fill: #000;
}

script

$(document).ready(function() {
    $('img[src$=".svg"]').each(function() {
        var $img = jQuery(this);
        var imgURL = $img.attr('src');
        var attributes = $img.prop("attributes");

        $.get(imgURL, function(data) {
            // Get the SVG tag, ignore the rest
            var $svg = jQuery(data).find('svg');

            // Remove any invalid XML tags
            $svg = $svg.removeAttr('xmlns:a');

            // Loop through IMG attributes and apply on SVG
            $.each(attributes, function() {
                $svg.attr(this.name, this.value);
            });

            // Replace IMG with SVG
            $img.replaceWith($svg);
        }, 'xml');
    });
});

43voto

aldel Points 3193

Vous pouvez maintenant utiliser le CSS filter propriété en la plupart des navigateurs modernes (y compris Edge, mais pas IE11). Il fonctionne sur les images SVG ainsi que sur d'autres éléments. Vous pouvez utiliser hue-rotate o invert pour modifier les couleurs, bien qu'ils ne vous permettent pas de modifier différentes couleurs indépendamment. J'utilise la classe CSS suivante pour afficher une version "désactivée" d'une icône (où l'original est une image SVG avec une couleur saturée) :

.disabled {
    opacity: 0.4;
    filter: grayscale(100%);
    -webkit-filter: grayscale(100%);
}

Cela le rend gris clair dans la plupart des navigateurs. Dans IE (et probablement dans Opera Mini, que je n'ai pas testé), il est sensiblement estompé par la propriété d'opacité, ce qui est quand même très bien, même si ce n'est pas du gris.

Voici un exemple avec quatre classes CSS différentes pour l'interface utilisateur de l'utilisateur. Twemoji icône de cloche : original (jaune), la classe "handicapé" ci-dessus, hue-rotate (vert), et invert (bleu).

.twa-bell {
  background-image: url("https://twemoji.maxcdn.com/svg/1f514.svg");
  display: inline-block;
  background-repeat: no-repeat;
  background-position: center center;
  height: 3em;
  width: 3em;
  margin: 0 0.15em 0 0.3em;
  vertical-align: -0.3em;
  background-size: 3em 3em;
}
.grey-out {
  opacity: 0.4;
  filter: grayscale(100%);
  -webkit-filter: grayscale(100%);
}
.hue-rotate {
  filter: hue-rotate(90deg);
  -webkit-filter: hue-rotate(90deg);
}
.invert {
  filter: invert(100%);
  -webkit-filter: invert(100%);
}

<!DOCTYPE html>
<html>

<head>
</head>

<body>
  <span class="twa-bell"></span>
  <span class="twa-bell grey-out"></span>
  <span class="twa-bell hue-rotate"></span>
  <span class="twa-bell invert"></span>
</body>

</html>

26voto

seanjacob Points 651

Vous pouvez également utiliser CSS mask , accordé Support du navigateur n'est pas bon, mais vous pourriez utiliser une solution de rechange

.frame {
    background: blue;
    -webkit-mask: url(image.svg) center / contain no-repeat;
}

16 votes

MDN précise que -webkit-mask ne doit pas être utilisé sur un site web de production.

3 votes

Ne colore pas le svg

1 votes

Il est peut-être pertinent de dire que maintenant, quatre ans plus tard, cette solution fonctionne dans tous les principaux navigateurs. Je viens de tester ici et c'est 100% ok.

24voto

trebor1979 Points 121

Si vous pouvez inclure des fichiers (PHP include ou include via votre CMS de choix) dans votre page, vous pouvez ajouter le code SVG et l'inclure dans votre page. Cela fonctionne de la même manière que de coller la source SVG dans la page, mais rend le balisage de la page plus propre.

L'avantage est que vous pouvez cibler des parties de votre SVG par le biais de CSS pour le survol - sans javascript.

http://codepen.io/chriscoyier/pen/evcBu

Il suffit d'utiliser une règle CSS comme celle-ci :

#pathidorclass:hover { fill: #303 !important; }

Notez que le !important est nécessaire pour remplacer la couleur de remplissage.

4 votes

Pour ceux qui utilisent AngularJS : <div ng-include="'svg.svg'"></div>

1 votes

Ce n'est pas une solution très élégante de stocker les données svg dans une base de données. Ce n'est pas faux, mais pomper des données xml/html/svg DOM à partir d'une API ou d'un CMS plutôt que d'utiliser des modèles ou d'autres actifs, c'est tout simplement faux.

0 votes

Merci pour cette contribution... Les sites les plus avancés aujourd'hui nichent des données svg pour permettre toutes sortes d'activités, sans cette réponse je ne l'aurais pas deviné !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X