web-dev-qa-db-fra.com

Comment styler SVG avec CSS externe?

J'ai plusieurs graphiques SVG dont j'aimerais modifier les couleurs via mes feuilles de style externes - et non directement dans chaque fichier SVG. Je ne mets pas les graphiques en ligne, mais les stocke dans mon dossier d'images et les pointe.

Je les ai implémentés de cette façon pour permettre aux info-bulles de fonctionner et j'ai également enveloppé chacun d'eux dans une balise <a> pour autoriser un lien.

<a href='http://youtube.com/...' target='_blank'><img class='socIcon' src='images/socYouTube.svg' title='View my videos on YouTube' alt='YouTube' /></a>

Et voici le code du graphique SVG:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
<g>
    <path d="M28.44......./>
</g>
</svg>

Je mets ce qui suit dans mon fichier CSS externe (main.css):

.socIcon g {fill:red;}

Pourtant, cela n’a aucun effet sur le graphique. J'ai aussi essayé .socIcon g path {} et .socIcon path {}.

Quelque chose ne va pas, peut-être que mon implémentation n'autorise pas les modifications CSS externes ou que j'ai raté une étape? J'apprécierais vraiment votre aide! J'ai juste besoin de la possibilité de modifier les couleurs du graphique SVG via ma feuille de style externe, mais je ne peux pas perdre l'info-bulle et la capacité de lien. (Je peux peut-être vivre sans tooltips cependant.) Merci!

70
Jordan H

Votre fichier main.css n’aura d’effet sur le contenu du fichier SVG que si celui-ci est inclus dans le code HTML:

https://developer.mozilla.org/en/docs/SVG_In_HTML_Introduction

<html>
  <body>
  <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
    <g>
      <path d="M28.44......./>
    </g>
  </svg>
</html>

Si vous souhaitez conserver votre fichier SVG dans des fichiers, le code CSS doit être défini à l'intérieur du fichier SVG. 

Vous pouvez le faire avec une balise de style:

http://www.w3.org/TR/SVG/styling.html#StyleElementExample

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
     width="50px" height="50px" viewBox="0 0 50 50">
  <defs>
    <style type="text/css"><![CDATA[
      .socIcon g {
        fill:red;
      }
    ]]></style>
  </defs>
  <g>
    <path d="M28.44......./>
  </g>
</svg>

Vous pouvez utiliser un outil côté serveur pour mettre à jour la balise de style en fonction du style actif. En Ruby, vous pouvez y parvenir avec Nokogiri. SVG est juste du XML. Donc, il existe probablement de nombreuses bibliothèques XML disponibles qui peuvent probablement atteindre cet objectif.

Si vous ne pouvez pas faire cela, vous devrez simplement les utiliser comme s'il s'agissait de PNG; créer un ensemble pour chaque style et enregistrer leurs styles en ligne.

70
RGB

Vous pouvez faire ce que vous voulez, avec une mise en garde (importante): les chemins dans votre symbole ne peuvent pas être stylés indépendamment via CSS externe - vous ne pouvez définir les propriétés que pour le symbole entier avec cette méthode. Donc, si vous avez deux chemins dans votre symbole et que vous voulez qu'ils aient des couleurs de remplissage différentes, cela ne fonctionnera pas, mais si vous voulez que tous vos chemins soient identiques, cela devrait fonctionner.

Dans votre fichier html, vous voulez quelque chose comme ça:

<style>
  .fill-red { fill: red; }
  .fill-blue { fill: blue; }
</style>

<a href="//www.example.com/">
  <svg class="fill-red">
    <use xlink:href="images/icons.svg#example"></use>
  </svg>
</a>

Et dans le fichier SVG externe, vous voulez quelque chose comme ceci:

<svg xmlns="http://www.w3.org/2000/svg">
   <symbol id="example" viewBox="0 0 256 256">
    <path d="M120.... />
  </symbol>
</svg>

Echangez la classe sur la balise svg (dans votre html) de fill-red à fill-blue et ta-da ... vous avez le bleu au lieu de rouge.

Vous pouvez partiellement contourner la limitation de la possibilité de cibler les chemins séparément avec le CSS externe en mélangeant et en faisant correspondre le CSS externe avec du CSS en ligne sur des chemins spécifiques, car le CSS en ligne aura la priorité. Cette approche fonctionnerait si vous faisiez quelque chose comme une icône blanche sur un fond coloré, où vous voulez changer la couleur de l'arrière-plan via le CSS externe, mais l'icône elle-même est toujours blanche (ou vice-versa). Donc, avec le même code HTML qu'auparavant et un peu comme ce code svg, vous obtiendrez un arrière-plan rouge et un chemin au premier plan blanc:

<svg xmlns="http://www.w3.org/2000/svg">
  <symbol id="example" viewBox="0 0 256 256">
    <path class="background" d="M120..." />
    <path class="icon" style="fill: white;" d="M20..." />
  </symbol>
</svg>
36
Adam Korman

Il est possible de styler un SVG en créant dynamiquement un élément de style en JavaScript et en l'ajoutant à l'élément SVG. Hacky, mais ça marche.

<object id="dynamic-svg" type="image/svg+xml" data="your-svg.svg">
    Your browser does not support SVG
</object>
<script>
    var svgHolder = document.querySelector('object#dynamic-svg');
    svgHolder.onload = function () {
        var svgDocument = svgHolder.contentDocument;
        var style = svgDocument.createElementNS("http://www.w3.org/2000/svg", "style");

        // Now (ab)use the @import directive to load make the browser load our css
        style.textContent = '@import url("/css/your-dynamic-css.css");';

        var svgElem = svgDocument.querySelector('svg');
        svgElem.insertBefore(style, svgElem.firstChild);
    };
</script>

Vous pouvez générer le code JavaScript dynamiquement dans PHP si vous le souhaitez - le fait que cela soit possible en JavaScript ouvre une myriade de possibilités.

5
Pete

Une approche possible consiste simplement à utiliser des filtres CSS pour modifier l'apparence des graphiques SVG dans le navigateur.

Par exemple, si vous avez un graphique SVG qui utilise une couleur de remplissage rouge dans le code SVG, vous pouvez le transformer en violet avec un paramètre de rotation de teinte de 180 degrés:

#theIdOfTheImgTagWithTheSVGInIt {
    filter: hue-rotate(180deg);
    -webkit-filter: hue-rotate(180deg);
    -moz-filter: hue-rotate(180deg);
    -o-filter: hue-rotate(180deg);
    -ms-filter: hue-rotate(180deg);
}

Expérimentez avec d'autres paramètres de rotation de teinte pour trouver les couleurs souhaitées.

Pour être clair, le CSS ci-dessus va dans le CSS qui est appliqué à votre document HTML. Vous stylisez la balise img dans le code HTML, mais pas le code du fichier SVG.

Et notez que cela ne fonctionnera pas avec des graphiques remplis en noir, blanc ou gris. Vous devez avoir une couleur réelle pour faire pivoter la teinte de cette couleur.

4
Simon White

Il devrait être possible de commencer par aligner les images svg externes. Regardez ici par exemple:

Remplacer toutes les images Svg par Inline Svg | JAVASCRIPT | Bibliothèque d'extraits de code de Jess Frazelle

3
Leo

"Je vais réellement changer les couleurs de ces images en fonction du schéma de couleurs choisi par l'utilisateur pour mon site." - Jordanil y a 10 heures

Je vous suggère d'utiliser PHP pour cela. Il n'y a vraiment pas de meilleur moyen de faire cela sans les polices d'icônes, et si vous résistez à les utiliser, vous pouvez essayer ceci:

<?php

    header('Content-Type: image/svg+xml');
    echo '<?xml version="1.0" encoding="utf-8"?>';
    $color = $_GET['color'];

?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
    <g>
        <path fill="<?php echo $color; ?>" d="M28.44..."/>
    </g>
</svg>

Et plus tard, vous pourrez utiliser ce fichier en tant que filename.php?color=#ffffff pour obtenir le fichier svg dans la couleur souhaitée.

2
SeinopSys

Lorsqu'il est utilisé dans une balise <image>, SVG doit être contenu dans un seul fichier pour des raisons de confidentialité. Ce bugzilla bug a plus de détails sur pourquoi il en est ainsi. Malheureusement, vous ne pouvez pas utiliser une balise différente telle que <iframe> car elle ne fonctionnera pas comme un lien, vous devrez donc incorporer le CSS à une balise <style> dans le fichier lui-même.

Une autre façon de le faire serait d’avoir les données SVG dans le fichier HTML principal, c’est-à-dire.

<a href='http://youtube.com/...' target='_blank'>
  <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
    <g>
        <path d="M28.44......./>
    </g>
  </svg>
</a>

Vous pouvez styler cela avec un fichier CSS externe en utilisant la balise HTML <link>.

2
Robert Longson

Une solution très rapide pour avoir un style dynamique avec une feuille de style css externe, si vous utilisez la balise <object> pour incorporer votre svg.

Cet exemple ajoutera une classe à la balise racine <svg> en cliquant sur un élément parent.

file.svg:

<?xml-stylesheet type="text/css" href="../svg.css"?>
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="">
  <g>
   <path/>
  </g>
 </svg>

html:

<a class="parent">
  <object data="file.svg"></object>
</a>

Jquery:

$(function() {
  $(document).on('click', '.parent', function(){
    $(this).find('object').contents().find('svg').attr("class","selected");
  }
});

sur clic élément parent:

 <svg xmlns="http://www.w3.org/2000/svg" viewBox="" class="selected">

alors vous pouvez gérer votre css

svg.css:

path {
 fill:none;
 stroke:#000;
 stroke-miterlimit:1.41;
 stroke-width:0.7px;
}

.selected path {
 fill:none;
 stroke:rgb(64, 136, 209);
 stroke-miterlimit:1.41;
 stroke-width:0.7px;
}
2
vhanahrni

Je sais que c’est un vieux post, mais je veux juste régler ce problème ... vous utilisez simplement vos cours au mauvais endroit: D

Tout d'abord, vous pouvez utiliser 

svg { fill: red; }

dans votre main.css pour le faire rouge. Cela a un effet. Vous pouvez également utiliser des sélecteurs de nœuds pour obtenir des chemins spécifiques.

La deuxième chose est que vous avez clarifié la classe à la img- Tag. 

<img class='socIcon'....

En fait, vous devriez le supprimer dans votre SVG. Si vous avez différents chemins, vous pouvez en définir plus, bien sûr.

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
<g>
    <path class="myClassForMyPath" d="M28.44......./>
</g>
</svg>

maintenant vous pouvez changer la couleur dans votre main.css comme

.myClassForMyPath {
    fill: yellow;
}
1
Dwza

Ce qui fonctionne pour moi: balise style avec la règle @import

<defs>
    <style type="text/css">
        @import url("svg-common.css");
    </style>
</defs>
0
Fordi
  1. Pour les styles externes

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">

  <style>
	@import url(main.css);
  </style>

  <g>
    <path d="M28.44......./>
  </g>
</svg>

  1. Pour les styles internes

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">

  <style>
	    .socIcon g {fill:red;}
  </style>

  <g>
    <path d="M28.44......./>
  </g>
</svg>

Remarque: les styles externes ne fonctionneront pas si vous incluez SVG dans la balise <img>. Cela fonctionnera parfaitement dans la balise <div>

0
Yuvraj Patil

@leo voici la version angularJS, merci encore 

G.directive ( 'imgInlineSvg', function () {

return {
    restrict : 'C',
    scope : true,
    link : function ( scope, elem, attrs ) {

        if ( attrs.src ) {

            $ ( attrs ).each ( function () {
                var imgID    = attrs.class;
                var imgClass = attrs.class;
                var imgURL   = attrs.src;

                $.get ( imgURL, function ( data ) {

                    var $svg = $ ( data ).find ( 'svg' );
                    if ( typeof imgID !== 'undefined' ) {
                        $svg = $svg.attr ( 'id', imgID );
                    }

                    if ( typeof imgClass !== 'undefined' ) {
                        $svg = $svg.attr ( 'class', imgClass + ' replaced-svg' );
                    }

                    $svg = $svg.removeAttr ( 'xmlns:a' );

                    elem.replaceWith ( $svg );

                } );

            } );
        }

    }

}

} );
0