I am trying to manipulate an external .svg file via CSS.
HTML
<body> <div class="mysvg"> <img src="decho.svg" alt="decho" width="200px"></img> </div> </body>
CSS
div.mysvg img { opacity: .3; transition: opacity 1s linear 0s; } div.mysvg img:hover { opacity: 1; }
This code works for opacity, but not for fill
or other svg specific attributes like stroke
. I am aware I can't do that with an img
tag, but I've been looking for hours and I can't find the correct way to do it with svg
or object
.
So basically, my questions is, how do I achieve the same result as the code which I linked, but to be able to manipulate fill, stroke etc. properties and it must be an external file, not just an inline svg code pasted in the html.
If someone is able to show me the correct way to do it, I'd be most grateful. Thanks.
EDIT:
I managed to do it by adding a css inside the .svg file itself. It must be right after the svg
opening tag.
<svg ...> <style type="text/css" media="screen"> <![CDATA[ g { fill: yellow; stroke: black; stroke-width: 1; transition: fill 1s linear 0s; } g:hover { fill: blue; } ]]> </style> <g> <path ...> </g> </svg>
You also need to insert it as an object
in the html, otherwise it won't work.
<object data="decho.svg" type="image/svg+xml">
Hopefully this helps to someone looking for an answer like mine in future. This is what helped me http://www.hongkiat.com/blog/scalable-vector-graphic-css-styling/.
Not only does it mean that SVG properties can be styled using CSS as presentation attributes or in style sheets, but this also can be applied to CSS pseudo-classes such as :hover or :active . SVG 2 also introduces more presentation attributes that can be used as styling properties.
If you load SVG as an image, you can't change how it is displayed using CSS or Javascript in the browser. If you want to change your SVG image, you have to load it using <object> , <iframe> or using <svg> inline.
The SVG <style> element allows style sheets to be embedded directly within SVG content. Note: SVG's style element has the same attributes as the corresponding element in HTML (see HTML's <style> element).
The fill property is a presentation attribute used to set the color of a SVG shape.
This is in my opinion the greatest flaw in svg: sandboxing.
Svg files are sandboxed: in their own document, which is why a typical 'fill:' style will not apply. Likewise, the css you write in your svg will not apply to the rest of your site.
Adding css directly to an svg: Not a good solution as you will end up rewriting the css in every svg you use.
The real solution: An "icon-system". Svg font-face or svg sprites. Read more about them here.
The reason opacity works: Opacity applies to the svg object/frame itself, not the contents of the svg (which are inaccessible).
I should also note that no matter how you load those svg's, inline, by reference, in an object, as a background, you will not be able to get inside the sandbox. This is why converting them to a font or using sprites is necessary for using hover, focus, and other effects/transitions.
This is possible providing the SVG is hosted on the same domain (thanks @FabienSnauwaert) and it does not have a fill colour defined on itself, and you do not contain a parent selector within the CSS. For example:
I have the following files:
icon-sprite.svg
I have omitted the other SVGs for clarity.
<svg xmlns="http://www.w3.org/2000/svg" style="width:0;height:0;visibility:hidden;"> <symbol viewBox="0 0 1500 828" id="icon-arrow-3pt-down"> <title>arrow-3pt-down</title> <path d="M1500 0H0l738.9 827.7z"/> </symbol> </svg>
test.html
<button class="button--large"> Large button <svg class="svg" width="20px" height="20px"> <use xlink:href="icon-sprite.svg#icon-arrow-3pt-down"></use> </svg> </button>
buttons.scss
.svg { fill: red; }
This would not work if I was to use body .svg
due to shadow DOM boundaries.
See this CSS Tricks article for more info
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With