外部CSSでSVGをスタイルする方法は?


102

各SVGファイル内ではなく、外部スタイルシートを使用して色を変更したいSVGグラフィックがいくつかあります。グラフィックをインラインで配置するのではなく、画像フォルダに保存して、ポイントします。

ツールチップが機能するようにこれらをこの方法で実装し<a>、リンクを許可するためにそれぞれをタグでラップしました。

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

そして、これが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>

次のコードを外部CSSファイル(main.css)に追加しました。

.socIcon g {fill:red;}

ただし、グラフィックには影響しません。.socIcon gパス{}と.socIconパス{}も試しました。

何かが正しくない、おそらく私の実装では外部CSSの変更が許可されていないか、または手順を逃しましたか?よろしくお願いします!外部スタイルシートを介してSVGグラフィックの色を変更する機能が必要なだけですが、ツールチップとリンク機能を失うことはありません。(私はツールチップなしで生きることができるかもしれません。)ありがとう!



svg { fill:red; }パスを試すか、クラス名を指定してください。たとえば、<path class="socIcon" d="M28.44 ..... />これでうまくいくはずです。
Dwza 2018

回答:


92

SVGファイルがHTMLにインラインで含まれている場合、main.cssファイルはSVGのコンテンツにのみ影響します。

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>

SVGをファイルに保持する場合は、CSSをSVGファイル内で定義する必要があります。

あなたはスタイルタグでそれを行うことができます:

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>

サーバー側のツールを使用して、アクティブなスタイルに応じてスタイルタグを更新できます。ルビーでは、これをNokogiriで実現できます。SVGは単なるXMLです。したがって、おそらくこれを実現できる多くのXMLライブラリが利用可能です。

それができない場合は、PNGであるかのように使用する必要があります。各スタイルのセットを作成し、それらのスタイルをインラインで保存します。


17
これは、SVGをキャッシュしてさまざまなスタイルを適用するメリットがないということですか?インラインはうまくキャッシュされていないようですが、他の方法では、イメージの多くのバージョンを作成する必要があり、それらをキャッシュすることによる利点がなくなります。
msg45f

もう1つの方法は、SVGを背景イメージデータURIとしてエンコードし、バージョンごとに異なる色を使用し、gzipを使用して重複によるファイルサイズを小さくすることです。
ラスキン

1
私の場合、SVGから要素スタイルをオーバーライドしたいと思いました。要素のスタイルの優先度が高いため、CSSが機能しませんでした。最も単純な解決策は、SVGのCSSスタイルに!importantを追加することでした。その後、すべてが大丈夫だった。重要なことを避けたい場合は、要素のスタイルをCSSに移動する必要があります。
David Gausmann

あなたはURLからSVG内のスタイルシートをロードすることはできません恥
clayRay

1
@clayRayあなたは、SVG2が完全なドラフトw3.org/TR/SVG2/styling.html#LinkElement
RGB

51

シンボル内のパスを外部CSS経由で個別にスタイル設定することはできません。このメソッドを使用して設定できるのは、シンボル全体のプロパティのみです。したがって、シンボルに2つのパスがあり、それらに異なる塗りつぶし色を設定したい場合、これは機能しませんが、すべてのパスを同じにしたい場合、これは機能します。

あなたのhtmlファイルでは、次のようなものが必要です:

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

そして、外部SVGファイルでは、次のようなものが必要です。

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

svgタグのクラスを(htmlで)からfill-redto fill-blueとta-daに入れ替えます。赤ではなく青になります。

インラインCSSが優先されるため、外部CSSを特定のパスのインラインCSSと混合して一致させることにより、外部CSSで個別にパスをターゲットにできるという制限を部分的に回避できます。この方法は、色付きの背景に対して白いアイコンのようなものを実行していて、外部CSSを介して背景の色を変更したいが、アイコン自体は常に白い(またはその逆)場合に機能します。したがって、以前と同じHTMLで、このsvgコードのようなものを使用すると、赤い背景と白い前景パスが得られます。

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

良い答えです。ただし、警告は本当にあるべきだと思います。適切なリファレンス(caniuseより詳細):css-tricks.com/svg-fragment-identifiers-work
ptim

これが解決策です!実際には、svgコンテンツ全体をsymbol要素でラップする必要はありません。つまりid、svg要素にを与えるだけでよいため、次のようにします。 `<svg id = example" 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

以下を使用して、SVGファイルに外部cssファイルへのリンクを含めることができます。

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

あなたはタグを開く後にこれを置く必要があります:

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

svgファイルを変更する必要があるため、これは完全なソリューションではありませんが、一度変更すると、すべてのsvgファイルに対して1つのcssファイルですべてのスタイル変更を行うことができます。


うわー、これは動作しますが、賛成投票は1つだけです...このソリューションはすべての状況に適していますか?それはとても簡単です、なぜこれが選ばれた答えではないのですか?
Bruno Vincent

重要なのは、スタイル定義を一元化することです。スタイルを設定するSVGが10個あるとします。次に、CSSへの参照を、影響を受ける必要のあるすべてのSVGにコピーする必要があります。また、CSSのファイル名/場所が変更された場合、10個のSVGで更新する必要があります。CSSクラスは、物理的なCSSファイルへの参照よりもはるかに象徴的です。
フランス

<img>タグを介して読み込まれたsvgは、外部コンテンツ(たとえば、スタイルシート)を読み込まないことに注意してください。
ムースモラル

7

JavaScriptでスタイル要素を動的に作成し、それをSVG要素に追加することで、SVGのスタイルを設定できます。ハッキーですが、動作します。

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

必要に応じて、JavaScriptをPHPで動的に生成できます。これがJavaScriptで可能であるという事実により、無数の可能性が開かれます。


ちょっと私は実際にあなたの解決策が好きでそれはうまくいきますが、あなたがOSコースを手伝うつもりなら、私は状況にそれを採用する必要があります、私は<defs>の中にスタイルタグを持っています私はそれらを手動で削除してこのコードを実行して作成することができますスタイル、defsを削除してから、要素を再作成したり、更新したりする方法があります。また、URLが定義されていないエラーURLが取得されました助けてください、ありがとう
Kamel Mili

6

あなたが取ることができる1つのアプローチは、ブラウザでのSVGグラフィックスの外観を変更するためにCSSフィルタを使用することです。

たとえば、SVGコード内で赤色の塗りつぶし色を使用するSVGグラフィックがある場合、色相回転設定を180度にして紫色にすることができます。

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

他の色相回転設定を試して、必要な色を見つけます。

明確にするために、上記のCSSはHTMLドキュメントに適用されるCSSに含まれます。HTMLコードのimgタグをスタイリングするのではなく、SVGのコードをスタイリングします。

また、塗りつぶしが黒、白、または灰色のグラフィックスでは機能しないことに注意してください。その色の色相を回転させるには、その中に実際の色が必要です。


4

あなたが使用している場合、外部のCSSスタイルシートで動的なスタイルを持つ非常に迅速なソリューション <object>タグをてsvgを埋め込ん。

この例では、クラスをルートに追加します <svg>、親要素をクリックしたタグにします。

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

親要素をクリック:

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

その後、あなたはあなたの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;
}

動作しないようですが、動作する例を追加できますか?
Jeanluca Scaljeri 2017年

4

最初に外部svg画像をインライン化することで実行できるはずです。以下のコードは、すべてのSVG画像を Jess FrazelleによるインラインSVGで置き換えたものです。

$('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);
  });
});

3
これは、htmlと同じドメインでホストされているイメージがある場合、またはイメージサーバーで特別に構成されたクロスドメインポリシーがある場合にのみ機能することに注意してください。$ .getはajaxを使用し、有効な許可アクセスヘッダーがない場合、外部サーバーからの画像の読み込みに失敗します
user151496

これは伝説的です
ティノコスタ 'エルニーニョ'

2

<image>タグで使用する場合、プライバシー上の理由から、SVGは単一のファイルに含める必要があります。このBugzillaのバグには、なぜそうなのかについての詳細が記載されています。残念ながら、などの別のタグを使用することはできません。<iframe>リンクとして機能しないため<style>、ファイル内のタグにCSSを埋め込む必要があります。

これを行うもう1つの方法は、メインのhtmlファイル内にSVGデータを含めることです。

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

HTML <link>タグを使用して、外部CSSファイルでスタイルを設定できます。


2
ファイル内にスタイルを配置できません。ユーザーが自分のサイトに選択した配色に基づいて、これらの画像の色を実際に変更します。現在の実装では、デフォルトのスタイルを上書きするスタイルシートをメインページに追加しています。埋め込まれたSVGグラフィックに影響を与えるために、そのファイルに色の変更を入れたかったのです。しかし、SVGファイル内からスタイルシートにリンクする必要があるので、これは機能しません(JavaScriptを使用してすべてのSVGファイルにそのリンクを追加する方法がない限り)。確かに、外部のSVGファイル、外部のCSS、リンク、ツールチップを許可する方法があります。
ジョーダンH

1
ブラウザのセキュリティモデルにより、目的の操作を実行できません。画像として使用する場合、JavaScriptを使用してSVGを操作することはできません。アニメーションpngまたはgifファイルのように画像として使用する場合、SVGはすべて1つのファイルに含まれ、スクリプトアクセスはありません。
Robert Longson 2013

1

「ユーザーが自分のサイトで選択した配色に基づいて、これらの画像の色を実際に変更します。」- ヨルダン 10時間前

これにはPHPを使用することをお勧めします。アイコンフォントなしでこれを行うには本当に良い方法はありません、そしてそれらを使用することに抵抗するなら、これを試すことができます:

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

そして、後でこのファイルを使用filename.php?color=#ffffffして、svgファイルを目的の色で取得できます。


6
このコードは、ユーザーの入力をチェックしないことに注意してください-何が色として供給することができ、あなたのSVGは、いくつかの非常に興味深い方法でレンダリングされる可能性があります...わからない、それはあなたに影響を与えますが、あなたはそれを習慣にする必要がある場合は、必ず検証のユーザー入力。このような何かが役立つでしょう:(if (!preg_match('/^[#][0-9a-f]{6}$/i', $_GET['color'])) die('Oops!');それを最初のPHPブロックのどこかに置きます)。
johndodo 2013

1

私のために働くもの:@importルールのあるスタイルタグ

<defs>
    <style type="text/css">
        @import url("svg-common.css");
    </style>
</defs>

1

私はそれが古い記事であることを知っていますが、この問題を解決するために...あなたはクラスを間違った場所で使用しています:D

まず最初にあなたが使うことができる

svg { fill: red; }

あなたの中でmain.cssそれを赤くするために。これには効果があります。ノードセレクターを適切に使用して、特定のパスを取得することもできます。

次に、クラスをimg-Tagに宣言しました。

<img class='socIcon'....

実際には、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 class="myClassForMyPath" d="M28.44......./>
</g>
</svg>

今、あなたはmain.css好きなように色を変えることができます

.myClassForMyPath {
    fill: yellow;
}

これを試してみましたが、他の多くの答えがすでに言っているように、それは機能しません。SVG内のクラスにスタイルを適用することはできません。
フランスの

@Fransはファイルとしてsvgを含めていますか、または上記の例のようにsvgソースを持っていますか?これは、svgの使用方法に依存することを念頭に置いているためです。imgによるインクルードは機能しません。
Dwza

正確には、HTMLにSVGをインライン化した場合にのみ機能します。しかし、それはあなたの例がすることではありません。外部(つまり、インラインではない)SVGを使用します。HTMLでCSSを使用して外部SVGをスタイルする方法はないようです。
フランスの

私の例を正しく試しましたか?つまり、外部からのcssファイルが含まれていますか?<?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
Dwza

はい、わかりました<?xml-stylesheet ... ?>。SVG 内に宣言があります。それはうまくいくと思います。<link rel="stylesheet" ... >SVGの内部を推奨する他の回答と同様です。また、同じ問題があります(スタイルシートを指すようにすべてのSVGを更新する必要があります。スタイルシートの名前または場所を変更すると、すべてのSVGを再度変更する必要があります)。
フランス

1
  1. 外部スタイルの場合

<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. 内部スタイル用

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

注:SVGを<img>タグ内に含めると、外部スタイルは機能しません。<div>タグ内で完全に機能します


0

@leoここにangularJSバージョンがあります、ありがとうございます

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

                } );

            } );
        }

    }

}

} );

-1

このメソッドは、svgがWebブラウザー内で表示される場合に機能しますが、このコードがサーバーにアップロードされ、svgアイコンのクラスが背景画像であるかのようにコード化されるとすぐに、色が失われ、デフォルトの色に戻ります。色のsvgクラスと表示の最上層クラスの両方とsvgの位置が両方とも同じディレクトリにマッピングされているにもかかわらず、外部スタイルシートから色を変更できないようです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.