Wie formatiere ich SVG mit externem CSS?

102

Ich habe mehrere SVG-Grafiken, deren Farben ich über meine externen Stylesheets ändern möchte - nicht direkt in jeder SVG-Datei. Ich stelle die Grafiken nicht in eine Linie, sondern speichere sie in meinem Bilderordner und zeige auf sie.

Ich habe sie auf diese Weise implementiert, damit QuickInfos funktionieren, und ich habe sie jeweils in ein <a>Tag eingeschlossen, um einen Link zu ermöglichen.

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

Und hier ist der Code der SVG-Grafik:

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

Ich habe Folgendes in meine externe CSS-Datei (main.css) eingefügt:

.socIcon g {fill:red;}

Es hat jedoch keine Auswirkung auf die Grafik. Ich habe auch .socIcon g path {} und .socIcon path {} ausprobiert.

Etwas stimmt nicht, vielleicht erlaubt meine Implementierung keine externen CSS-Änderungen, oder ich habe einen Schritt verpasst? Ich würde mich sehr über Ihre Hilfe freuen! Ich brauche nur die Möglichkeit, die Farben der SVG-Grafik über mein externes Stylesheet zu ändern, aber ich kann die Tooltip- und Link-Fähigkeit nicht verlieren. (Ich kann jedoch möglicherweise ohne Tooltips leben.) Danke!

Jordan H.
quelle
Versuchen Sie svg { fill:red; }oder geben Sie Ihrem Pfad einen Klassennamen. ZB <path class="socIcon" d="M28.44 ..... />sollte dies den Trick tun.
Dwza

Antworten:

92

Ihre main.css-Datei würde sich nur dann auf den Inhalt der SVG auswirken, wenn die SVG-Datei inline im HTML-Code enthalten ist:

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>

Wenn Sie Ihre SVG in Dateien behalten möchten, muss das CSS in der SVG-Datei definiert werden.

Sie können dies mit einem Style-Tag tun:

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>

Sie können ein Tool auf der Serverseite verwenden, um das Style-Tag abhängig vom aktiven Style zu aktualisieren. In Ruby konnte man dies mit Nokogiri erreichen. SVG ist nur XML. Es sind also wahrscheinlich viele XML-Bibliotheken verfügbar, die dies wahrscheinlich erreichen können.

Wenn Sie das nicht können, müssen Sie sie nur so verwenden, als wären sie PNGs. Erstellen eines Sets für jeden Stil und Speichern der Stile inline.

RGB
quelle
17
Bedeutet dies, dass es keine Methode gibt, um vom Zwischenspeichern der SVG und dem Anwenden eines unterschiedlichen Stils zu profitieren? Inline scheint nicht gut zwischenzuspeichern, während andere Methoden das Erstellen vieler Versionen des Bildes erfordern würden, wodurch jeglicher Vorteil des Zwischenspeicherns entfällt.
msg45f
Eine andere Möglichkeit besteht darin, die SVGs als Hintergrundbilddaten-Uris mit unterschiedlichen Farben in jeder Version zu codieren und sich auf gzip zu verlassen, um die Dateigröße aufgrund der Duplizierung zu verringern.
Ruskin
1
In meinem Fall wollte ich Elementstile aus der SVG überschreiben. Mein CSS hat nicht funktioniert, da die Elementstile eine höhere Priorität hatten. Die einfachste Lösung bestand darin, dem CSS-Stil für die SVG einen! Wichtigen hinzuzufügen. Dann war alles in Ordnung. Wenn Sie! Wichtig vermeiden möchten, müssen Sie die Elementstile in das CSS verschieben.
David Gausmann
Schade, dass Sie kein Stylesheet in ein SVG von einer URL
laden können
1
@clayRay Sie können dies auf diese Weise tun, sobald SVG2 fertig ist. Entwurf w3.org/TR/SVG2/styling.html#LinkElement
RGB
51

Sie können mit einer (wichtigen) Einschränkung tun, was Sie wollen: Die Pfade in Ihrem Symbol können nicht unabhängig über externes CSS gestaltet werden. Mit dieser Methode können Sie nur die Eigenschaften für das gesamte Symbol festlegen. Wenn Sie also zwei Pfade in Ihrem Symbol haben und möchten, dass diese unterschiedliche Füllfarben haben, funktioniert dies nicht. Wenn Sie jedoch möchten, dass alle Pfade gleich sind, sollte dies funktionieren.

In Ihrer HTML-Datei möchten Sie ungefähr Folgendes:

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

Und in der externen SVG-Datei möchten Sie so etwas:

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

Tauschen Sie die Klasse auf dem svgTag (in Ihrem HTML) von fill-redbis fill-blueund ta-da ... Sie haben Blau statt Rot.

Sie können die Einschränkung teilweise umgehen, dass Sie die Pfade separat mit externem CSS ausrichten können, indem Sie das externe CSS mit bestimmten Inline-CSS auf bestimmten Pfaden mischen und abgleichen, da das Inline-CSS Vorrang hat. Dieser Ansatz funktioniert, wenn Sie so etwas wie ein weißes Symbol vor einem farbigen Hintergrund ausführen, bei dem Sie die Farbe des Hintergrunds über das externe CSS ändern möchten, das Symbol selbst jedoch immer weiß ist (oder umgekehrt). Mit demselben HTML-Code wie zuvor und so etwas wie diesem SVG-Code erhalten Sie einen roten Hintergrund und einen weißen Vordergrundpfad:

<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>
Adam Korman
quelle
Gute Antwort. Ich denke, die Einschränkung sollte wirklich lauten: Browser-Unterstützung! gute Referenz (mehr Details als caniuse): css-tricks.com/svg-fragment-identifiers-work
ptim
Das ist eine Lösung! Tatsächlich ist es nicht erforderlich, den gesamten svg-Inhalt in ein symbolElement zu packen , dh Sie können iddem svg-Element einfach eine geben , also: `<svg id = Beispiel" xmlns = " w3.org/2000/svg " viewBox = "0 0 256 256 "> <path class =" background "d =" M120 ... "/> <path class =" icon "style =" fill: white; "d =" M20 ... "/> </ svg > `
SimoneMSR
11

Sie können in Ihre SVG-Dateien einen Link zu einer externen CSS-Datei aufnehmen, indem Sie Folgendes verwenden:

<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="mystyles.css" type="text/css"/>

Sie müssen dies nach dem Öffnen des Tags einfügen:

<svg>
  <link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="mystyles.css" type="text/css"/>
  <g>
    <path d=.../>
  </g>
</svg>

Es ist keine perfekte Lösung, da Sie SVG-Dateien ändern müssen, aber Sie ändern sie einmal und dann können alle Stiländerungen in einer CSS-Datei für alle SVG-Dateien vorgenommen werden.

Jacek Mamot
quelle
Wow, das funktioniert, aber nur 1 Gegenstimme ... ist diese Lösung für alle Situationen gut? Es ist so einfach, warum ist das nicht die gewählte Antwort?
Bruno Vincent
7

Sie können eine SVG-Datei formatieren, indem Sie dynamisch ein Stilelement in JavaScript erstellen und an das SVG-Element anhängen. Hacky, aber es funktioniert.

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

Sie können das JavaScript dynamisch in PHP generieren, wenn Sie möchten - die Tatsache, dass dies in JavaScript möglich ist, eröffnet eine Vielzahl von Möglichkeiten.

Pete
quelle
Hey, ich mag deine Lösung wirklich und sie funktioniert, aber ich muss sie in meine Situation übernehmen, wenn du bereit bist, dem Kurs zu helfen. Ich habe in <defs> ein Style-Tag, das ich manuell löschen und diesen Code ausführen kann, damit er erstellt wird Ein Stil, gibt es eine Möglichkeit, die Defs zu löschen und dann das Element neu zu erstellen, wie Sie es getan haben, oder es einfach zu aktualisieren, und auch die URL hat eine Fehler-URL nicht definiert. Können Sie bitte helfen, danke
Kamel Mili
6

Sie können lediglich CSS-Filter verwenden, um das Erscheinungsbild der SVG-Grafiken im Browser zu ändern.

Wenn Sie beispielsweise eine SVG-Grafik haben, die eine Füllfarbe Rot im SVG-Code verwendet, können Sie sie mit einer Farbton-Rotations-Einstellung von 180 Grad lila drehen:

#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);
}

Experimentieren Sie mit anderen Einstellungen für die Farbtonrotation, um die gewünschten Farben zu finden.

Das obige CSS wird in das CSS aufgenommen, das auf Ihr HTML-Dokument angewendet wird. Sie gestalten das img-Tag im HTML-Code und nicht den Code der SVG.

Beachten Sie auch, dass dies bei Grafiken mit einer Füllung aus Schwarz, Weiß oder Grau nicht funktioniert. Sie müssen eine tatsächliche Farbe haben, um den Farbton dieser Farbe zu drehen.

Simon White
quelle
4

Eine sehr schnelle Lösung für einen dynamischen Stil mit einem externen CSS-Stylesheet, falls Sie das <object>Tag zum Einbetten Ihres SVG verwenden.

In diesem Beispiel wird dem Root- <svg>Tag eine Klasse hinzugefügt, wenn Sie auf ein übergeordnetes Element klicken.

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

Klicken Sie auf übergeordnetes Element:

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

dann können Sie Ihre CSS verwalten

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;
}
vhanahrni
quelle
scheint nicht zu funktionieren, könnten Sie ein funktionierendes Beispiel hinzufügen?
Jeanluca Scaljeri
4

Dies sollte möglich sein, indem zuerst die externen SVG-Bilder eingefügt werden. Der folgende Code stammt aus dem Ersetzen aller SVG-Bilder durch Inline-SVG von Jess Frazelle.

$('img.svg').each(function(){
  var $img = $(this);
  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);
  });
});
Löwe
quelle
3
Es ist wichtig zu beachten, dass dies nur funktioniert, wenn Sie das Image in derselben Domäne wie das HTML gehostet haben oder eine speziell konfigurierte domänenübergreifende Richtlinie auf dem Image-Server haben. $ .get verwendet Ajax und kann das Image nicht von einem externen Server laden, wenn kein gültiger Header für den
zulässigen
Das ist legendär
Tino Costa 'El Nino'
2

Bei Verwendung in einem <image>Tag muss SVG aus Datenschutzgründen in einer einzigen Datei enthalten sein. Dieser Bugzilla-Bug enthält weitere Details dazu, warum dies so ist. Leider können Sie kein anderes Tag wie z. B. ein verwenden, <iframe>da dies nicht als Link funktioniert und Sie das CSS in ein <style>Tag in der Datei selbst einbetten müssen .

Eine andere Möglichkeit, dies zu tun, besteht darin, die SVG-Daten in der Haupt-HTML-Datei zu haben, d. H.

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

Sie können dies mit einer externen CSS-Datei mithilfe des HTML- <link>Tags formatieren.

Robert Longson
quelle
2
Ich kann die Stile nicht in die Dateien einfügen. Ich werde die Farben dieser Bilder basierend auf dem Farbschema ändern, das der Benutzer für meine Website ausgewählt hat. Meine aktuelle Implementierung besteht darin, der Hauptseite ein Stylesheet hinzuzufügen, das die Standardstile überschreibt. Ich wollte die Farbänderungen in diese Datei einfügen, um die eingebetteten SVG-Grafiken zu beeinflussen. Aber das würde nicht funktionieren, da ich aus der SVG-Datei heraus auf das Stylesheet verlinken muss (es sei denn, es gibt eine Möglichkeit, diesen Link auch mit JavaScript zu allen SVG-Dateien hinzuzufügen). Sicher gibt es eine Möglichkeit, externe SVG-Dateien, externes CSS, Links und Tooltips zuzulassen.
Jordan H
1
Aufgrund des Sicherheitsmodells des Browsers ist es nicht möglich, das zu tun, was Sie möchten. Sie können kein Javascript verwenden, um SVG zu manipulieren, wenn es als Bild verwendet wird. Stellen Sie sich SVG als Bild wie eine animierte PNG- oder GIF-Datei vor, alles in einer Datei und ohne Skriptzugriff.
Robert Longson
2

Ich weiß, dass es ein alter Beitrag ist, aber nur um dieses Problem zu lösen ... Sie verwenden Ihre Klassen nur am falschen Ort: D.

Zuallererst könnten Sie verwenden

svg { fill: red; }

in deinem main.css, um es rot zu bekommen. Dies hat Wirkung. Sie könnten wahrscheinlich auch Knotenselektoren verwenden, um bestimmte Pfade zu erhalten.

Zweitens haben Sie die Klasse zum img-Tag erklärt.

<img class='socIcon'....

Sie sollten es tatsächlich in Ihrem SVG deklamieren. Wenn Sie unterschiedliche Pfade haben, können Sie natürlich mehr definieren.

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

Jetzt können Sie die Farbe nach Ihren main.cssWünschen ändern

.myClassForMyPath {
    fill: yellow;
}
Dwza
quelle
1

"Ich werde die Farben dieser Bilder basierend auf dem Farbschema ändern, das der Benutzer für meine Website ausgewählt hat." - Jordanien vor 10 Stunden

Ich empfehle Ihnen, dafür PHP zu verwenden. Es gibt wirklich keinen besseren Weg, dies ohne Symbolschriftarten zu tun, und wenn Sie sich weigern, sie zu verwenden, können Sie Folgendes versuchen:

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

Und später können Sie diese Datei verwenden filename.php?color=#ffffff, um die SVG-Datei in der gewünschten Farbe zu erhalten.

SeinopSys
quelle
6
Beachten Sie, dass dieser Code keine Benutzereingaben überprüft - alles kann als Farbe angegeben werden und Ihr SVG kann auf sehr interessante Weise gerendert werden ... Sie sind sich nicht sicher, ob es Sie betrifft, aber Sie sollten es sich zur Gewohnheit machen, Benutzereingaben IMMER zu validieren. So etwas würde helfen: if (!preg_match('/^[#][0-9a-f]{6}$/i', $_GET['color'])) die('Oops!');(Platziere es irgendwo im Start-PHP-Block).
Johndodo
1

Was für mich funktioniert: Style-Tag mit @ Import-Regel

<defs>
    <style type="text/css">
        @import url("svg-common.css");
    </style>
</defs>
Fordi
quelle
1
  1. Für externe Stile

<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. Für interne Stile

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

Hinweis: Externe Stile funktionieren nicht, wenn Sie SVG in das <img>Tag aufnehmen. Es wird perfekt innerhalb des <div>Tags funktionieren

Yuvraj Patil
quelle
0

@leo hier ist die angleJS-Version, nochmals vielen Dank

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

                } );

            } );
        }

    }

}

} );
Tino Costa 'El Nino'
quelle
-1

Diese Methode funktioniert, wenn das SVG in einem Webbrowser angezeigt wird. Sobald dieser Code jedoch auf den Server hochgeladen und die Klasse für das SVG-Symbol so codiert wurde, als wäre es ein Hintergrundbild, geht die Farbe verloren und kehrt zur Standardfarbe zurück . Anscheinend kann die Farbe im externen Stylesheet nicht geändert werden, obwohl sowohl die SVG-Klasse für die Farbe als auch die oberste Ebenenklasse für die Anzeige und die Position des SVG demselben Verzeichnis zugeordnet sind.

HTMLGUY1999
quelle