Comment changer la couleur de l'image SVG en utilisant CSS (remplacement d'image jQuery SVG)?

437

Ceci est une auto-question d'un morceau de code pratique que j'ai trouvé.

Actuellement, il n'y a pas de moyen facile d'incorporer une image SVG et d'avoir ensuite accès aux éléments SVG via CSS. Il existe différentes méthodes d'utilisation des frameworks JS SVG, mais elles sont trop compliquées si vous ne faites qu'une simple icône avec un état de survol.

Voici donc ce que j'ai trouvé, qui est, je pense, de loin le moyen le plus simple d'utiliser des fichiers SVG sur un site Web. Il tire son concept des premières méthodes de remplacement de texte en image, mais pour autant que je sache, cela n'a jamais été fait pour les SVG.

Ceci est la question:

Comment incorporer un SVG et changer sa couleur en CSS sans utiliser de framework JS-SVG?

Drew Baker
la source
1
Malheureusement, la balise img ne fonctionne pas avec les fichiers svg dans IE, alors gardez cela à l'esprit. IE reconnaît les balises intégrées. Bref, beau travail!
2
Pour svg, vous devez utiliser la propriété css "fill". Pour les images, il convient d'utiliser "filtre". "Filtre" fonctionne en fait pour les deux, mais il n'est pas nécessaire de faire tout ce travail pour un graphique vectoriel.
Samy Bencherif

Réponses:

536

Tout d'abord, utilisez une balise IMG dans votre code HTML pour incorporer un graphique SVG. J'ai utilisé Adobe Illustrator pour créer le graphique.

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

C'est exactement comme si vous intégriez une image normale. Notez que vous devez définir l'IMG pour avoir une classe de svg. La classe «lien social» est juste à titre d'exemple. L'ID n'est pas requis, mais il est utile.

Ensuite, utilisez ce code jQuery (dans un fichier séparé ou en ligne dans la tête).

    /**
     * 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 cherche 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 CSS pour changer la couleur du SVG maintenant, comme ceci:

svg:hover path {
    fill: red;
}

Le code jQuery que j'ai écrit porte également sur l'ID et les classes des images d'origine. 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

Drew Baker
la source
6
Il peut parfois ne pas fonctionner dans Safari (par exemple), pour vous assurer que les données retournées sont lisibles, remplacez le });$ .get par}, 'xml');
Joan
29
Vous pourriez probablement même remplacer le sélecteur par img[src$=".svg"]et éliminer le besoin de la svgclasse.
Casey Chu
2
@LeonGaban Je ne pense pas qu'il existe un moyen de cibler le remplissage d'une image d'arrière-plan. Ce serait super utile si vous le pouviez!
Drew Baker
3
Un peu tard, @LeonGaban, mais une meilleure façon de le faire serait probablement de supprimer complètement l'attribut fill, et de s'appuyer sur un fichier CSS pour ajouter un remplissage au svg parent. $('#ico_company path').removeAttr('fill'). Ensuite, vous pouvez le faire #ico_company { fill: #ccc }dans votre fichier CSS
bioball
2
@Soaku, il serait facile que jQuery définisse tous les chemins pour être identiques à la couleur de la police en faisant quelque chose comme `var color = $ img.closest ('p'). Css ('color'); $ svg.find ('path'). attr ('fill', color); `Mais je pense que c'est un travail qu'il vaut mieux laisser au CSS.
Drew Baker
56

Style

svg path {
    fill: #000;
}

Scénario

$(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');
    });
});
Henrik Albrechtsson
la source
1
Si vous n'avez pas de largeur, cela en crée juste un avec un mauvais numéro. width="170.667"dans mon cas
stallingOne
2
Ce n'est pas parfait car il perd les dimensions img précédentes.
RichieHH
Bonjour, supposons que j'ai des svg différents avec des couleurs différentes chacun. En utilisant cette méthode, toutes mes couleurs svg deviennent les mêmes que le premier svg en boucle. Une idée comment puis-je manœuvrer pour que chaque couleur reste la même qu'avant?
tnkh
1
notez que si votre svg est également fabriqué à partir de non- pathformes (comme rect), vous devrez également les gérer en CSS
Mugen
33

Vous pouvez désormais utiliser la propriété CSSfilter dans 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-rotateou invertpour modifier les couleurs, bien qu'ils ne vous permettent pas de modifier les 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 Opera Mini, que je n'ai pas testé), il est sensiblement atténué par la propriété d'opacity, qui semble toujours assez bonne, bien qu'elle ne soit pas grise.

Voici un exemple avec quatre classes CSS différentes pour l' icône de cloche Twemoji : originale (jaune), la classe "désactivée" ci-dessus, hue-rotate(verte) et invert(bleue).

aldel
la source
Je viens de remarquer qu'invert est une bonne solution si vous ne voulez pas créer de polices d'icônes. J'ai utilisé ce code jQuery pour changer l'icône dans l'en-tête de mon site Web en fonction de la propriété de couleur CSS (notez que j'utilise des icônes png blanches):if ($('.w3-top img').css("color") == "rgb(0, 0, 0)") { $('.w3-top img').css("filter", "invert(100%)"); $('.w3-top img').css("-webkit-filter", "invert(100%)"); };
RedClover
Excellente approche. Modifié mon xml SVG pour ajouter la couleur de l'icône cible, puis utilisé une classe désactivée .icon pour le griser.
SushiGuy
Notez que les anciens Explores ne prennent pas en charge le filtre: w3schools.com/cssref/css3_pr_filter.asp
JillAndMe
25

Alternativement, vous pouvez utiliser CSS mask, la prise en charge du navigateur accordée n'est pas bonne, mais vous pouvez utiliser une solution de secours

.frame {
    background: blue;
    -webkit-mask: url(image.svg) center / contain no-repeat;
}
seanjacob
la source
14
MDN spécifie qu'il -webkit-maskne doit pas être utilisé sur un site Web de production.
vaindil
1
ne colore pas le svg
vishal
Il est peut-être pertinent de dire que maintenant, quatre ans plus tard, cette solution fonctionne dans tous les principaux navigateurs. Je viens de le tester ici et c'est 100% ok.
Daniel Lemes
23

Si vous pouvez inclure des fichiers (PHP inclure ou inclure 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 le collage de la source SVG dans la page, mais rend le balisage de page plus propre.

L'avantage est que vous pouvez cibler des parties de votre SVG via CSS pour le survol - aucun javascript requis.

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

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

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

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

trebor1979
la source
3
Pour ceux qui utilisent AngularJS:<div ng-include="'svg.svg'"></div>
Mikel
Ce n'est pas une solution très élégante pour stocker des données svg dans une base de données. Pas mal, mais pomper des données DOM xml / html / svg à partir d'une API ou d'un CMS plutôt que d'utiliser des modèles ou d'autres actifs semble tout simplement faux.
ChristoKiwi
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 n'aurais pas deviné ça!
webMan
De plus, si votre SVG a des zones transparentes, celles-ci ne compteront pas en vol stationnaire et vous pourrez rencontrer un "vol stationnaire flashy". Pour résoudre ce problème, ajoutez simplement un élément wrapper (un <a>, si cela vous convient), puis ajoutez-le à la règle CSS. #pathidorclass:hover, .wrapperclass:hover #pathidorclass { fill: green; }Ou même éliminez simplement le survol original du chemin SVG puisque vous le ciblez via l'élément wrapper maintenant de toute façon.
Neil Monroe
18

@Drew Baker a donné une excellente solution pour résoudre le problème. Le code fonctionne correctement. Cependant, ceux qui utilisent AngularJs peuvent trouver beaucoup de dépendance à jQuery. Par conséquent, j'ai pensé que c'était une bonne idée de coller pour les utilisateurs d'AngularJS, un code suivant la solution de @Drew Baker.

AngularJs façon du même code

1. Html : utilisez la balise ci-dessous dans votre fichier html:

<svg-image src="/icons/my.svg" class="any-class-you-wish"></svg-image>

2. Directive : ce sera la directive dont vous aurez besoin pour reconnaître la balise:

'use strict';
angular.module('myApp')
  .directive('svgImage', ['$http', function($http) {
    return {
      restrict: 'E',
      link: function(scope, element) {
        var imgURL = element.attr('src');
        // if you want to use ng-include, then
        // instead of the above line write the bellow:
        // var imgURL = element.attr('ng-include');
        var request = $http.get(
          imgURL,
          {'Content-Type': 'application/xml'}
        );

        scope.manipulateImgNode = function(data, elem){
          var $svg = angular.element(data)[4];
          var imgClass = elem.attr('class');
          if(typeof(imgClass) !== 'undefined') {
            var classes = imgClass.split(' ');
            for(var i = 0; i < classes.length; ++i){
              $svg.classList.add(classes[i]);
            }
          }
          $svg.removeAttribute('xmlns:a');
          return $svg;
        };

        request.success(function(data){
          element.replaceWith(scope.manipulateImgNode(data, element));
        });
      }
    };
  }]);

3. CSS :

.any-class-you-wish{
    border: 1px solid red;
    height: 300px;
    width:  120px
}

4. Test unitaire au karma-jasmin :

'use strict';

describe('Directive: svgImage', function() {

  var $rootScope, $compile, element, scope, $httpBackend, apiUrl, data;

  beforeEach(function() {
    module('myApp');

    inject(function($injector) {
      $rootScope = $injector.get('$rootScope');
      $compile = $injector.get('$compile');
      $httpBackend = $injector.get('$httpBackend');
      apiUrl = $injector.get('apiUrl');
    });

    scope = $rootScope.$new();
    element = angular.element('<svg-image src="/icons/icon-man.svg" class="svg"></svg-image>');
    element = $compile(element)(scope);

    spyOn(scope, 'manipulateImgNode').andCallThrough();
    $httpBackend.whenGET(apiUrl + 'me').respond(200, {});

    data = '<?xml version="1.0" encoding="utf-8"?>' +
      '<!-- Generator: Adobe Illustrator 17.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">' +
      '<!-- Obj -->' +
      '<!-- Obj -->' +
      '<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"' +
      'width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">' +
        '<g>' +
          '<path fill="#F4A902" d=""/>' +
          '<path fill="#F4A902" d=""/>' +
        '</g>' +
      '</svg>';
    $httpBackend.expectGET('/icons/icon-man.svg').respond(200, data);
  });

  afterEach(function() {
    $httpBackend.verifyNoOutstandingExpectation();
    $httpBackend.verifyNoOutstandingRequest();
  });

  it('should call manipulateImgNode atleast once', function () {
    $httpBackend.flush();
    expect(scope.manipulateImgNode.callCount).toBe(1);
  });

  it('should return correct result', function () {
    $httpBackend.flush();
    var result = scope.manipulateImgNode(data, element);
    expect(result).toBeDefined();
  });

  it('should define classes', function () {
    $httpBackend.flush();
    var result = scope.manipulateImgNode(data, element);
    var classList = ["svg"];
    expect(result.classList[0]).toBe(classList[0]);
  });
});
Max
la source
1
votre solution ne fonctionne pas, pourrait être<div ng-include="/icons/my.svg" class="any-class-you-wish"></div>
Guillaume Vincent
@guillaumevincent si vous voulez l'utiliser avec ng-includealors changez simplement cette ligne var imgURL = element.attr('src');envar imgURL = element.attr('ng-include');
Max
C'est une solution très pratique, mais soyez prudent en l'utilisant trop, car cela peut affecter les performances assez durement - IE un ensemble de 5 icônes de partage répétées sur une liste d'articles ou quelque chose comme ça.
skxc
1
Il y a un problème avec votre code dans IE. Vous pouvez utiliser juste if (typeof(imgClass) !== 'undefined') { $svg.setAttribute("class", imgClass); }au lieu de fractionner et de boucle.
Robert Bokori
2
Super travail! Mais pour certaines images, vous devez saisir le premier élément de svg ( angular.element(data)[0];) et le faire fonctionner avec l'utilisation d'IE if ($svg.getAttribute('class')) { $svg.setAttribute('class', $svg.getAttribute('class') + ' ' + imgClass); } else { $svg.setAttribute('class', imgClass); }. De plus, vous voudrez peut-être ajouter cache: truedes options, $http.getsinon votre page pourrait devenir très lente.
leo
16

Je réalise que vous voulez accomplir cela avec CSS, mais juste un rappel au cas où ce serait une petite image simple - vous pouvez toujours l'ouvrir dans Notepad ++ et changer le chemin / le remplissage de l'élément:

<path style="fill:#010002;" d="M394.854,205.444c9.218-15.461,19.102-30.181,14.258-49.527
    ...
    C412.843,226.163,402.511,211.451,394.854,205.444z"/>

Cela pourrait sauver une tonne de scripts laids. Désolé si c'est hors de la base, mais parfois les solutions simples peuvent être négligées.

... même l'échange de plusieurs images svg peut être plus petit que certains extraits de code pour cette question.

DShultz
la source
7

J'ai écrit une directive pour résoudre ce problème avec AngularJS. Il est disponible ici - ngReusableSvg .

Il remplace l'élément SVG après son rendu et le place à l'intérieur d'un divélément, ce qui rend son CSS facilement modifiable. Cela permet d'utiliser le même fichier SVG à différents endroits en utilisant différentes tailles / couleurs.

L'utilisation est simple:

<object oa-reusable-svg
        data="my_icon.svg"
        type="image/svg+xml"
        class="svg-class"
        height="30"  // given to prevent UI glitches at switch time
        width="30">
</object>

Après cela, vous pouvez facilement avoir:

.svg-class svg {
    fill: red; // whichever color you want
}
Omri Aharon
la source
Salut, merci d'avoir fourni cette solution. Je l'ai essayé et il donne: <div ng-click = "eventHandler ()" ng-class = "classEventHandler ()" style = "height: 30px; width: 30px; float: left;" class = "svg-class" id = "my-svg" height = "30" width = "30"> [[object SVGSVGElement]] </div> Dans le html, il met simplement [[object SVGSVGElement]]. Savez-vous quel est le problème? Une autre question, cela a-t-il un impact important sur les performances ou puis-je l'utiliser sur de nombreux svg sur une page? Et enfin, il est toujours en angulaire 1.3 (le tonneau).
bersling
Quelle version d'angular utilisez-vous? Vous n'avez pas rencontré votre problème ... c'est peut-être quelque chose avec le SVG? En termes de performances, le commutateur est relativement lourd, je l'ai utilisé moi-même comme 10 et c'était bien .. Je suppose que cela dépend de la quantité / taille, alors essayez-le et expérimentez-le. Quel est le problème avec la tonnelle? Utilisez-vous une version différente et il y a un conflit?
Omri Aharon
5

TL / DR: ALLEZ ici-> https://codepen.io/sosuke/pen/Pjoqqp

Explication:

Je suppose que vous avez quelque chose en HTML comme ceci:

<img src="/img/source.svg" class="myClass">

Certainement aller la route du filtre, ce est à dire. votre svg est très probablement noir ou blanc. Vous pouvez appliquer un filtre pour qu'il soit de la couleur que vous voulez, par exemple, j'ai un svg noir que je veux vert menthe. Je l'inverse d'abord pour qu'il soit blanc (qui est techniquement toutes les couleurs RVB sur le plein), puis je joue avec la saturation de teinte, etc. Pour bien faire les choses:

filter: invert(86%) sepia(21%) saturate(761%) hue-rotate(92deg) brightness(99%) contrast(107%);

Encore mieux, vous pouvez simplement utiliser un outil pour convertir l'hex que vous voulez en un filtre pour vous: https://codepen.io/sosuke/pen/Pjoqqp

AhrenFullStop
la source
C'est une excellente solution uniquement en CSS, plus le codepen de hex au filtre est tout simplement génial.
Richi González
4

Voici une version knockout.jsbasée sur la réponse acceptée:

Important: il nécessite également jQuery pour le remplacement, mais j'ai pensé qu'il pourrait être utile à certains.

ko.bindingHandlers.svgConvert =
    {
        'init': function ()
        {
            return { 'controlsDescendantBindings': true };
        },

        'update': function (element, valueAccessor, allBindings, viewModel, bindingContext)
        {
            var $img = $(element);
            var imgID = $img.attr('id');
            var imgClass = $img.attr('class');
            var imgURL = $img.attr('src');

            $.get(imgURL, function (data)
            {
                // Get the SVG tag, ignore the rest
                var $svg = $(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');

        }
    };

Ensuite, appliquez simplement data-bind="svgConvert: true"à votre tag img.

Cette solution remplace complètement la imgbalise par un SVG et toute liaison supplémentaire ne serait pas respectée.

Simon_Weaver
la source
2
C'est bien! Si vous souhaitez passer au niveau supérieur, nous avons une version mise à jour qui inclut la mise en cache, donc le même SVG n'est pas demandé deux fois. github.com/funkhaus/style-guide/blob/master/template/js/…
Drew Baker
J'étais un peu inquiet à ce sujet mais je n'ai pas eu le temps de m'en occuper moi-même. Je
voulais
1
@DrewBaker en fait, j'étais plus préoccupé par le fait que la balise img demanderait le fichier, puis le getdemanderait à nouveau. J'ai envisagé de remplacer l' attribut par srcun data-srcattribut sur la imgbalise, mais j'ai conclu que les navigateurs modernes sont probablement assez intelligents pour mettre en cache le fichier de toute façon
Simon_Weaver
3

Voici un code sans framework, uniquement des js purs:

document.querySelectorAll('img.svg').forEach(function(element) {
            var imgID = element.getAttribute('id')
            var imgClass = element.getAttribute('class')
            var imgURL = element.getAttribute('src')

            xhr = new XMLHttpRequest()
            xhr.onreadystatechange = function() {
                if(xhr.readyState == 4 && xhr.status == 200) {
                    var svg = xhr.responseXML.getElementsByTagName('svg')[0];

                    if(imgID != null) {
                         svg.setAttribute('id', imgID);
                    }

                    if(imgClass != null) {
                         svg.setAttribute('class', imgClass + ' replaced-svg');
                    }

                    svg.removeAttribute('xmlns:a')

                    if(!svg.hasAttribute('viewBox') && svg.hasAttribute('height') && svg.hasAttribute('width')) {
                        svg.setAttribute('viewBox', '0 0 ' + svg.getAttribute('height') + ' ' + svg.getAttribute('width'))
                    }
                    element.parentElement.replaceChild(svg, element)
                }
            }
            xhr.open('GET', imgURL, true)
            xhr.send(null)
        })
user3144480
la source
3

Il existe une bibliothèque open source appelée SVGInject qui utilise l' onloadattribut pour déclencher l'injection. Vous pouvez trouver le projet GitHub sur https://github.com/iconfu/svg-inject

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
1
Je préfère cette solution, car elle prend en charge les SVG ajoutés dynamiquement.
VickyB
2

Si nous avons un plus grand nombre de ces images svg, nous pouvons également prendre l'aide de fichiers de polices.
Des sites comme https://glyphter.com/ peuvent nous obtenir un fichier de police à partir de nos svgs.


Par exemple

@font-face {
    font-family: 'iconFont';
    src: url('iconFont.eot');
}
#target{
    color: white;
    font-size:96px;
    font-family:iconFont;
}
Abhishek Borar
la source
5
Personnellement, je déteste la technique des "images en tant que police". Il est difficile d'ajouter / éditer des images, ajoute beaucoup de balisage absurde. Les polices doivent être des polices, les images doivent être des images, etc.
Drew Baker
D'accord. Vous devez également mémoriser / rechercher les images attribuées aux personnages. mais pour le cas spécifique où les images sont utilisées comme icônes / boutons / puces, agissent plus comme du texte que des médias, les fichiers de polices peuvent également être une alternative
Abhishek Borar
même github n'utilise plus de police pour l'icône github.com/blog/2112-delivering-octicons-with-svg
gagarine
2

Vous pouvez utiliser data-image pour cela. en utilisant data-image (data-URI), vous pouvez accéder au SVG comme en ligne.

Voici un effet de survol en utilisant du CSS pur et du SVG.

Je sais que c'est désordonné, mais vous pouvez le faire de cette façon.

 .action-btn {
    background-size: 20px 20px;
    background-position: center center;
    background-repeat: no-repeat;
    border-width: 1px;
    border-style: solid;
    border-radius: 30px;
    height: 40px;
    width: 60px;
    display: inline-block;
 }

.delete {
     background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg version='1.1' id='Capa_1' fill='#FB404B' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='482.428px' height='482.429px' viewBox='0 0 482.428 482.429' style='enable-background:new 0 0 482.428 482.429;' xml:space='preserve'%3e%3cg%3e%3cg%3e%3cpath d='M381.163,57.799h-75.094C302.323,25.316,274.686,0,241.214,0c-33.471,0-61.104,25.315-64.85,57.799h-75.098 c-30.39,0-55.111,24.728-55.111,55.117v2.828c0,23.223,14.46,43.1,34.83,51.199v260.369c0,30.39,24.724,55.117,55.112,55.117 h210.236c30.389,0,55.111-24.729,55.111-55.117V166.944c20.369-8.1,34.83-27.977,34.83-51.199v-2.828 C436.274,82.527,411.551,57.799,381.163,57.799z M241.214,26.139c19.037,0,34.927,13.645,38.443,31.66h-76.879 C206.293,39.783,222.184,26.139,241.214,26.139z M375.305,427.312c0,15.978-13,28.979-28.973,28.979H136.096 c-15.973,0-28.973-13.002-28.973-28.979V170.861h268.182V427.312z M410.135,115.744c0,15.978-13,28.979-28.973,28.979H101.266 c-15.973,0-28.973-13.001-28.973-28.979v-2.828c0-15.978,13-28.979,28.973-28.979h279.897c15.973,0,28.973,13.001,28.973,28.979 V115.744z'/%3e%3cpath d='M171.144,422.863c7.218,0,13.069-5.853,13.069-13.068V262.641c0-7.216-5.852-13.07-13.069-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C158.074,417.012,163.926,422.863,171.144,422.863z'/%3e%3cpath d='M241.214,422.863c7.218,0,13.07-5.853,13.07-13.068V262.641c0-7.216-5.854-13.07-13.07-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C228.145,417.012,233.996,422.863,241.214,422.863z'/%3e%3cpath d='M311.284,422.863c7.217,0,13.068-5.853,13.068-13.068V262.641c0-7.216-5.852-13.07-13.068-13.07 c-7.219,0-13.07,5.854-13.07,13.07v147.154C298.213,417.012,304.067,422.863,311.284,422.863z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e ");
     border-color:#FB404B;
     
 }
 
 .delete:hover {
     background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg version='1.1' id='Capa_1' fill='#fff' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='482.428px' height='482.429px' viewBox='0 0 482.428 482.429' style='enable-background:new 0 0 482.428 482.429;' xml:space='preserve'%3e%3cg%3e%3cg%3e%3cpath d='M381.163,57.799h-75.094C302.323,25.316,274.686,0,241.214,0c-33.471,0-61.104,25.315-64.85,57.799h-75.098 c-30.39,0-55.111,24.728-55.111,55.117v2.828c0,23.223,14.46,43.1,34.83,51.199v260.369c0,30.39,24.724,55.117,55.112,55.117 h210.236c30.389,0,55.111-24.729,55.111-55.117V166.944c20.369-8.1,34.83-27.977,34.83-51.199v-2.828 C436.274,82.527,411.551,57.799,381.163,57.799z M241.214,26.139c19.037,0,34.927,13.645,38.443,31.66h-76.879 C206.293,39.783,222.184,26.139,241.214,26.139z M375.305,427.312c0,15.978-13,28.979-28.973,28.979H136.096 c-15.973,0-28.973-13.002-28.973-28.979V170.861h268.182V427.312z M410.135,115.744c0,15.978-13,28.979-28.973,28.979H101.266 c-15.973,0-28.973-13.001-28.973-28.979v-2.828c0-15.978,13-28.979,28.973-28.979h279.897c15.973,0,28.973,13.001,28.973,28.979 V115.744z'/%3e%3cpath d='M171.144,422.863c7.218,0,13.069-5.853,13.069-13.068V262.641c0-7.216-5.852-13.07-13.069-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C158.074,417.012,163.926,422.863,171.144,422.863z'/%3e%3cpath d='M241.214,422.863c7.218,0,13.07-5.853,13.07-13.068V262.641c0-7.216-5.854-13.07-13.07-13.07 c-7.217,0-13.069,5.854-13.069,13.07v147.154C228.145,417.012,233.996,422.863,241.214,422.863z'/%3e%3cpath d='M311.284,422.863c7.217,0,13.068-5.853,13.068-13.068V262.641c0-7.216-5.852-13.07-13.068-13.07 c-7.219,0-13.07,5.854-13.07,13.07v147.154C298.213,417.012,304.067,422.863,311.284,422.863z'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e ");        
     background-color: #FB404B;
    }
<a class="action-btn delete">&nbsp;</a>

Vous pouvez convertir votre svg en URL de données ici

  1. https://codepen.io/elliz/full/ygvgay
  2. https://websemantics.uk/tools/svg-to-background-image-conversion/
patelarpan
la source
Cela ne fonctionnerait pas pour les SVG complexes où vous souhaitez uniquement que certains chemins / polygones / etc. changent en survolant à droite?
Drew Baker
Non, vous pouvez ... mais c'est très complexe
patelarpan
It just solutions for icon
patelarpan
Si certains fonctionnent avec l'icône. Alors c'est super. Bootstrap 4 utilise également cette technique
patelarpan
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:

  1. Mozilla Firefox 59.0.2 (64 bits) Linux

entrez la description de l'image ici

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

entrez la description de l'image ici

  1. Opera 53.0.2907.37 Linux

entrez la description de l'image ici

Benjamin
la source
1

La solution sélectionnée est parfaite si vous voulez que jQuery traite tous les éléments svg de votre DOM et que votre DOM soit de taille raisonnable. Mais si votre DOM est volumineux et que vous décidez de charger des parties de votre DOM dynamiquement, cela n'a vraiment aucun sens d'avoir à réanalyser l'intégralité du DOM juste pour mettre à jour les éléments svg. Utilisez plutôt un plugin jQuery pour ce faire:

/**
 * A jQuery plugin that loads an svg file and replaces the jQuery object with its contents.
 *
 * The path to the svg file is specified in the src attribute (which normally does not exist for an svg element).
 *
 * The width, height and class attributes in the loaded svg will be replaced by those that exist in the jQuery object's
 * underlying html. Note: All other attributes in the original element are lost including the style attribute. Place
 * any styles in a style class instead.
 */
(function ($) {
    $.fn.svgLoader = function () {
        var src = $(this).attr("src");
        var width = this.attr("width");
        var height = this.attr("height");
        var cls = this.attr("class");
        var ctx = $(this);

        // Get the svg file and replace the <svg> element.
        $.ajax({
            url: src,
            cache: false
        }).done(function (html) {
            let svg = $(html);
            svg.attr("width", width);
            svg.attr("height", height);
            svg.attr("class", cls);
            var newHtml = $('<a></a>').append(svg.clone()).html();
            ctx.replaceWith(newHtml);
        });

        return this;
    };

}(jQuery));

Dans votre html, spécifiez un élément svg comme suit:

<svg src="images/someSvgFile.svg" height="45" width="45" class="mySVGClass"/>

Et appliquez le plugin:

$(".mySVGClass").svgLoader();
AndroidDev
la source
Oui, il existe certainement des moyens plus efficaces d'utiliser le code que j'ai donné. Voici comment nous l'utilisons réellement sur les sites de production. Il met en cache les SVG! github.com/funkhaus/style-guide/blob/master/template/js/…
Drew Baker
1

pour: les animations d'événement de survol, nous pouvons laisser les styles à l'intérieur du fichier svg, comme un

<svg xmlns="http://www.w3.org/2000/svg">
<defs>
  <style>
  rect {
    fill:rgb(165,225,75);
    stroke:none;
    transition: 550ms ease-in-out;
    transform-origin:125px 125px;
  }
  rect:hover {
    fill:rgb(75,165,225);
    transform:rotate(360deg);
  }
  </style>
</defs>
  <rect x='50' y='50' width='150' height='150'/>
</svg>

vérifiez ceci sur svgshare

ghett
la source