How to style SVG with external CSS?

2019-01-03 13:43发布

I have several SVG graphics I'd like to modify the colors of via my external style sheets - not directly within each SVG file. I'm not putting the graphics in-line, but storing them in my images folder and pointing to them.

I have implemented them in this way to allow tooltips to work, and I also wrapped each in an <a> tag to allow a link.

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

And here is the code of the SVG graphic:

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

I put the following in my external CSS file (main.css):

.socIcon g {fill:red;}

Yet it has no effect on the graphic. I also tried .socIcon g path {} and .socIcon path {}.

Something isn't right, perhaps my implementation doesn't allow external CSS modifications, or I missed a step? I'd really appreciate your help! I just need the ability to modify the colors of the SVG graphic via my external stylesheet, but I cannot lose the tooltip and link ability. (I may be able to live without tooltips though.) Thanks!

12条回答
Deceive 欺骗
2楼-- · 2019-01-03 14:29

You can do what you want, with one (important) caveat: the paths within your symbol can't be styled independently via external CSS -- you can only set the properties for the entire symbol with this method. So, if you have two paths in your symbol and want them to have different fill colors, this won't work, but if you want all your paths to be the same, this should work.

In your html file, you want something like this:

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

And in the external SVG file you want something like this:

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

Swap the class on the svg tag (in your html) from fill-red to fill-blue and ta-da... you have blue instead of red.

You can partially get around the limitation of being able to target the paths separately with external CSS by mixing and matching the external CSS with some in-line CSS on specific paths, since the in-line CSS will take precedence. This approach would work if you're doing something like a white icon against a colored background, where you want to change the color of the background via the external CSS but the icon itself is always white (or vice-versa). So, with the same HTML as before and something like this svg code, you'll get you a red background and a white foreground path:

<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>
查看更多
爷的心禁止访问
3楼-- · 2019-01-03 14:34

It is possible to style an SVG by dynamically creating a style element in JavaScript and appending it to the SVG element. Hacky, but it works.

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

You could generate the JavaScript dynamically in PHP if you want to - the fact that this is possible in JavaScript opens a myriad of possibilities.

查看更多
相关推荐>>
4楼-- · 2019-01-03 14:34

It should be possible to do by first inlining the external svg images. Look here for example:

Replace All Svg Images With Inline Svg | JAVASCRIPT | Code Snippet Library by Jess Frazelle

查看更多
Rolldiameter
5楼-- · 2019-01-03 14:37

I know its an old post, but just to clear this problem... you just using your classes at the wrong place :D

First of all you could use

svg { fill: red; }

in your main.css to get it red. This does have effect. You could propably use node selectors as well to get specific pathes.

Second thing is, you declaired the class to the img-Tag.

<img class='socIcon'....

You actually should declair it inside your SVG. if you have diffrent pathes you could define more of course.

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

now you could change the color in your main.css like

.myClassForMyPath {
    fill: yellow;
}
查看更多
forever°为你锁心
6楼-- · 2019-01-03 14:40

When used in an <image> tag SVG must be contained in a single file for privacy reasons. This bugzilla bug has more details on exactly why this is so. Unfortunately you can't use a different tag such as an <iframe> because that won't work as a link so you'll have to embed the CSS in a <style> tag within the file itself.

One other way to do this would be to have the SVG data within the main html file i.e.

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

You could style that with an external CSS file using the HTML <link> tag.

查看更多
家丑人穷心不美
7楼-- · 2019-01-03 14:45

A very quick solution to have dynamic style with an external css stylesheet, in case you are using the <object> tag to embed your svg.

This example will add a class to the root <svg> tag on click on a parent element.

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

on click parent element :

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

then you can manage your 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;
}
查看更多
登录 后发表回答