Change colour of SVG loaded from file - javascript
I have an SVG loaded from file in an tag like so...
<img class="svgbutton" src="filepath/icon.svg">
the svg is just a simple icon in a single colour. Is it possible to control the colour of the svg in someway (possibly a filter?), either using css or javascript?
Or is the only proper way to do this to draw it fully in the script..?
This can require some Javascript or Jquery, often a bit tricky.
The simpliest way that I can think about that may work is this CSS code:
.element {
-webkit-mask: url(yourimage.svg) center / contain no-repeat;
background: red;
}
However, some browers do not support this, there are fallbacks though.
I suggest to use inline SVG like this in HTML:
<div style="color: red;">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
[ ... ]
</svg>
</div>
By doing so you may use standard CSS (and JavaScript if required for dynamic changes, but keep in mind that there are pseudo-classes to style mouse-over and much more). The trick here is to apply the inherited CSS color to the SVG fill color with fill: currentColor;
<style type="text/css">
svg {
fill: currentColor;
}
</style>
You could also keep multiple symbols together, hide thie whole "collection" with CSS display: none; on the <svg ...> element and reuse the symbols separately in multiple places.
A symbol definition in the "collection":
<g id="icon1">
<path class="path1" d="M22 20c-2 2-2 4-4 4s-4-2-6-4-4-4-4-6 2-2 4-4-4-8-6-8-6 6-6 6c0 4 4.109 12.109 8 16s12 8 16 8c0 0 6-4 6-6s-6-8-8-6z"></path>
</g>
Use it anywhere like this:
<svg viewBox="0 0 64 64">
<use xlink:href="#icon1"></use>
</svg>
NOTE: xlink:href is deprecated as of SVG 2.0 and is being replaced by href which might not yet be supported by your browser though...
You could also color multiple paths in one symbol differently:
<style type="text/css">
.path1 {
color: blue;
fill: currentColor;
}
</style>
Keep experimenting with classes and pseudo-classes before choosing JavaScript for dynamically changing your element's classes as it might not be necessary.
Related
svg from sprite import as background image
In my vanilla JS project I like pulling svg images from svg sprite (which is in separated svg file). What bothers me a lot is that in this way I can only use svg images in HTML code, but I would also love to use them in css file. Is something like that even possible? SVG sprite (located in separated file in my code). I heard that it doesn't work in tools like codepen so I only attach it here as plain text: <svg width="0" height="0" class="hidden"> <symbol id="il_uk_coverage" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 61 61"><title>UK Coverage</title> <path d="M31,1A30,30,0,1,0,61,31,30,30,0,0,0,31,1ZM50,52.53A2.81,2.81,0,0,0,50.16,50,2.86,2.86,0,0,0,49,48.65,25.23,25.23,0,0,0,33.41,5.87a2.4,2.4,0,0,0-.13-.59,2.21,2.21,0,0,0-1.75-1.41,9.65,9.65,0,0,1-1.07-.26,5.26,5.26,0,0,0-3.7-.06c-.94.44-1.33.87-2.28,3.08a25.23,25.23,0,0,0-2.25,48,2.17,2.17,0,0,0,1.9,3c1.36.08,3.12.15,4.18.19h.12a3.22,3.22,0,0,0,2.48-1.16l.38-.47A25.44,25.44,0,0,0,35,55.92a32.51,32.51,0,0,0,3.57-.12c2.1-.22,4.18-.62,6.19-1,.83-.16,1.65-.32,2.47-.46a4.58,4.58,0,0,0,.77-.21,28.9,28.9,0,1,1,2-1.58Zm-16.44.76-1.65,0a3,3,0,0,0-2.4,1.11l-.55.66a.64.64,0,0,1-.51.23c-.82,0-2.08-.08-3.23-.14L27,53.36c.09-.09.5-.58.72-.85l.1-.12c1-1.21,1.87-1.36,3.91-1.45a3.08,3.08,0,0,0,2.19-1,2.81,2.81,0,0,0,.67-1.37,1.3,1.3,0,0,0-.34-1.17,1.33,1.33,0,0,0-1.16-.37,4,4,0,0,1-.48.07,10.54,10.54,0,0,1-6.7-1.77l3-2.66a1.28,1.28,0,0,0,.35-1.46l-1.07-2.69h4.46A1.3,1.3,0,0,0,34,37.36c.17-2,.42-5-2.12-7.17a3.48,3.48,0,0,1-.26-1l-.07-.36a2.37,2.37,0,0,0-.93-1.78,2.56,2.56,0,0,0-2.1-.5L26.72,27a.43.43,0,0,1-.37-.09.47.47,0,0,1-.17-.34,10.9,10.9,0,0,1,.08-2c.29-1.81.33-4.09-2-5.74a1.13,1.13,0,0,1-.26-.28,1.33,1.33,0,0,1-.16-.83A19.84,19.84,0,0,1,25.1,12l.22-.57c1.73-4.35,2.16-5.39,2.53-5.56a3.34,3.34,0,0,1,1.92.21l.61.16a.53.53,0,0,0,0,.12h0c-.32.36-.65.72-1,1.06a4,4,0,0,0-1,4.53,1.3,1.3,0,0,0,1.5.85l5.28-1.12a1.68,1.68,0,0,1-.08,1.74,15.12,15.12,0,0,0-1.28,3.17C33.4,18,33,18.57,32.31,18.82l-.08,0a1.33,1.33,0,0,0-.48.23,1.29,1.29,0,0,0-.49,1.14v0a1.35,1.35,0,0,0,.37.85,2.33,2.33,0,0,0,.17.28A2.85,2.85,0,0,0,34,22.82a3.27,3.27,0,0,1,.5.14c1.64.92,2.27,2.49,2.72,4.57a4.87,4.87,0,0,0,3.43,4.13,1.64,1.64,0,0,1,.43.58c.65,1.37,1.26,2.8,1.84,4.19l.56,1.31a1.65,1.65,0,0,1,.12.32,1.19,1.19,0,0,1,0,.16,2.58,2.58,0,0,0,2.92,3.09c1.15-.18,1.57,0,1.91.44A4.84,4.84,0,0,1,49,43.5l.12.48-3.79,4.26A1.3,1.3,0,0,0,46,50.36l1.59.43a.26.26,0,0,1,.19.18.2.2,0,0,1,0,.2,1.23,1.23,0,0,1-.95.59l-2.51.47c-2,.38-4,.78-6,1A37.77,37.77,0,0,1,33.51,53.29ZM23,53.56a23.94,23.94,0,0,1,.81-45.42c-.27.68-.58,1.45-.94,2.37l-.23.58c-.05.12-.25.64-.48,1.41A20.37,20.37,0,0,0,11,26.86a6.2,6.2,0,0,0-1.13,2.71A1.32,1.32,0,0,0,9.9,30a1.85,1.85,0,0,0,.63.86s0,.08,0,.12A20.49,20.49,0,0,0,25.76,50.78l-.07.08-.53.64Zm5.88-24.41a2,2,0,0,0,0,.26l.06.31a4,4,0,0,0,1.08,2.41,4.26,4.26,0,0,1,1.35,3.72c-.15,0-.29,0-.43,0A4.91,4.91,0,0,1,26.11,31a5,5,0,0,1,.22-1.45,3.09,3.09,0,0,0,.91,0ZM26.53,41.36l-2.44,2.13s-.06.07-.1.1a14.39,14.39,0,0,1-7.14-9.9,2.78,2.78,0,0,0,1.3.33h0a3.15,3.15,0,0,0,1.43-.38l.11-.07.57-.38a11,11,0,0,0,6.07,7.72Zm.29,8.35a19.17,19.17,0,0,1-15-18.52,4.23,4.23,0,0,0,1.27-.45l.12-.07,0,0c.07.08.15.2.24.31a3.82,3.82,0,0,0,1.2,1.2,4.27,4.27,0,0,1,.67.42,15.66,15.66,0,0,0,8,12.08,2.49,2.49,0,0,0-.09.82,2.45,2.45,0,0,0,1.14,1.91,15.92,15.92,0,0,0,3.36,1.67A5.24,5.24,0,0,0,26.82,49.71ZM21.35,18.58a15.67,15.67,0,0,0-4.26,5.11,6.26,6.26,0,0,0-2-.3,2.56,2.56,0,0,0-1.13.3,4.17,4.17,0,0,0-.93.65,19.14,19.14,0,0,1,8.74-10.15,20.71,20.71,0,0,0-.47,3.38A4.15,4.15,0,0,0,21.35,18.58Zm-3,12.79a.41.41,0,0,1-.17.05c-.12,0-.37-.21-.67-.45A8.34,8.34,0,0,0,16,30a3.34,3.34,0,0,1-.4-.5,5.49,5.49,0,0,0-.7-.8,1.74,1.74,0,0,0-.75-.59,1.72,1.72,0,0,0-.79-.12A6.94,6.94,0,0,1,15,26.06l.11-.07a3.66,3.66,0,0,1,3.24,1.79l1.32,2.67Zm7.43,5.52a2.11,2.11,0,0,0-.21,2l0,.1a9.7,9.7,0,0,1-4.13-6.6,2.33,2.33,0,0,0,.67-2.87l-.47-.94a9.59,9.59,0,0,1,2-3.82,16.72,16.72,0,0,0-.06,1.85,3.05,3.05,0,0,0,1.15,2.29,3.61,3.61,0,0,0,.36.23A6.45,6.45,0,0,0,24.81,31a6.23,6.23,0,0,0,2.53,5A2.09,2.09,0,0,0,25.75,36.89Zm-4.92-10-.15-.29a5.72,5.72,0,0,0-2.39-2.43,14.54,14.54,0,0,1,3.53-4.31s0,0,0,0a3.5,3.5,0,0,0,.94,1,2.25,2.25,0,0,1,1,1.85A10.81,10.81,0,0,0,20.83,26.91ZM51.61,43.19c0-.1-.06-.2-.08-.3a6.69,6.69,0,0,0-1.15-2.79,4.43,4.43,0,0,0-.71-.67A20.47,20.47,0,0,0,37.87,11.7a5.81,5.81,0,0,0-1-2.18A1.3,1.3,0,0,0,35.51,9l-4.8,1a1.5,1.5,0,0,1,.45-.67c.63-.62,1.22-1.28,1.72-1.86a2.3,2.3,0,0,0,.21-.33,23.93,23.93,0,0,1,18.52,36Zm-5.78-6.47-.09-.22a15.55,15.55,0,0,0,1-5.51,15.74,15.74,0,0,0-10.1-14.68,12,12,0,0,1,.7-1.58,4.73,4.73,0,0,0,.57-1.64,19.18,19.18,0,0,1,10.6,25.75,5.18,5.18,0,0,0-2.43-.07A3,3,0,0,0,45.83,36.72Zm-4-7.33a10.88,10.88,0,0,0-4.3-7.22,7.37,7.37,0,0,0-1.83-1.48,4,4,0,0,0-1-.36,6.24,6.24,0,0,0,1.5-2.79A14.46,14.46,0,0,1,45.44,31,14.06,14.06,0,0,1,45,34.66c-.49-1.17-1-2.36-1.55-3.53A4,4,0,0,0,41.86,29.39Zm-1.48-.8A3.64,3.64,0,0,1,39.72,27l-.09-.41A10,10,0,0,1,40.38,28.59Z"></path> </symbol> </svg> This usage in my HTML works fine: <svg class="icon-size-md" viewBox="0 0 40 40"> <use href="../resources/icons/sprite-all.svg#coverage"></use> </svg> I would like to import that svg from sprite into my CSS code e.g. for background-image. .wrapper { height: 50px; width: 50px; background: url('../resources/icons/sprite-all.svg#coverage'); // this doesn't work } <div class="wrapper"></div> But it doesn't work for me. If this wasn't possible way how to use svg from sprite in both: <use> and css file, is there ANY other way? (and renaming "symbol" to "g" doesn't work for me)
How can I change an SVG color without using an ID in the SVG file itself?
Newbie to working with SVGs and I've run into a problem. Basically I'm using the Noun Project API pro version ( https://api.thenounproject.com/ ) to scrape icons as SVGs. Right now, I save the SVGs in a local folder. I want to be able to change the color of the icon (right now they download as black, and I want to change the color). I am loading the SVGs via the tag with a reference to the folder where the SVGs are being saved. I know it's fairly simple to change the color using vanilla JS (using document.getElementById('svgObject').contentDocument, and then accessing the inner document using a unique id). The problem is that the SVGs I save don't have any ID, and I don't know how to give them an ID. Right now, I'm looping through the folder and displaying the folder contents in a webpage. That's all working fine, but I can't manage to figure out how to change the color. Basically, I just want all the icons in the folder to be set to a different color (for example, they could all be set to "red." They don't need to each have a different color). How do I do that without specifying the actual ID (since the SVG doesn't include an ID upon download), or else how do I add an ID to the SVG tag itself?
Assuming you have a bunch of svgs on your page and you'd like to change the color of each to the same color, you could do the following: function changeSvgColors() { const svgs = document.getElementsByTagName('svg') for (let i = 0; i < svgs.length; i++) { svgs[i].setAttribute('fill', 'red') } } This will loop through every svg on your page and set their fill attribute to red. Essentially, this is equivalent to doing this: <svg viewBox="0 0 512 512" fill="red"> ... </svg> Here's a quick demo: JSFiddle Alternatively, if you're using something like the img tag to load your svgs onto your page, using object instead would let you do the same thing as above. Assuming your html looks like the following: <div> <object data="http://localhost:5000/image.svg" type="image/svg+xml" ></object> </div> Then, function changeSvgColors() { const objects = document.getElementsByTagName('object') for (let i = 0; i < objects.length; i++) { const object = objects[i] const svg = object.contentDocument.rootElement svg.setAttribute('fill', 'red') } }
One option would be using the svg as an image (or as an object if you prefer) and filters to change the color. #theImage{filter: invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg) brightness(104%) contrast(97%);} <img id="theImage" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/bone300.svg" > Please read this article: Solved with CSS! Colorizing SVG Backgrounds Yet another option is using the svg as a mask. Keep in mind that the support for mask is not that good. #theDiv{ display: inline-block; width:300px; height:134px; -webkit-mask: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/bone300.svg); mask: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/bone300.svg); mask-size: cover; background:red; } <div id="theDiv"></div> But the best option would be to use the svg inline. You may save all your icons in a root svg element with width="0"; height="0"; position="absolute". Next you can use the icons with <use> and you change the color using the fill attribute <use fill="red" xlink:href="..... or styling it in CSS
You can give the SVGs a class instead of an id & set the color using javascript's getElementsByClassName This Mozilla article explains: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName
Your best shot in achiveing this is to make use of the fill attibute for svg elements. Now, you can work this out two ways Method 1: Using img tag like this <img src="your_file.svg" />. In this case, you will need to edit the file directly, and that's it, it should reflect everywhere you reference the svg. Method 2: You can use svg as inline like below. The advantage in this approach is that if you have varying instance of the same svg, then this is the way to go. On the other side, if your svg stays same throughout the app, this goes against the DRY principle. svg { max-width: 200px; } <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"> <path d="M25,7l28,36l40-18l-36,25l19,44l-27-37l-41,17l36-26z" fill="#cfc"/> <ellipse cx="50" cy="50" rx="32" ry="30" stroke="#fc0" fill="none" stroke-width="11"/> <path d="M63,2l-7,43l42,17l-45-6l-16,42l7,-45l-42-16l45,6z" fill="#3cc"/> </svg>
If you don't mind having the svg all one color, you could set the fill attribute of the svg to currentcolor. Then it will take on the color of the element that it is in. #span1 { color: red; } #span2 { color: blue; } #span3 { color: green; } <body> <span id=span1> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="150" height="150" fill-rule="evenodd" fill="currentcolor"> <title>HTML5 Logo</title> <path d="M12,0 188,0 172,180 100,200 28,180Z M45,37 156,37 154,59 69,59 71,81 152,81 146,149 100,162 54,149 52,114 74,114 76,132 100,139 124,132 127,103 51,103Z"/> </svg> </span> <span id=span2> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="150" height="150" fill-rule="evenodd" fill="currentcolor"> <title>HTML5 Logo</title> <path d="M12,0 188,0 172,180 100,200 28,180Z M45,37 156,37 154,59 69,59 71,81 152,81 146,149 100,162 54,149 52,114 74,114 76,132 100,139 124,132 127,103 51,103Z"/> </svg> </span> <span id=span3> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="150" height="150" fill-rule="evenodd" fill="currentcolor"> <title>HTML5 Logo</title> <path d="M12,0 188,0 172,180 100,200 28,180Z M45,37 156,37 154,59 69,59 71,81 152,81 146,149 100,162 54,149 52,114 74,114 76,132 100,139 124,132 127,103 51,103Z"/> </svg> </span> </body>
How to change part of an inline SVG's appearance when hovering over another outside source div or text element using javascript?
I have been looking for an HTML/CSS only solution to this issue for about 2 weeks now and nothing has come from any research or experimentation. I have come to the understanding that this is not possible with CSS so I was wondering if anyone could provided me a Javascript example that could possibly work for my case as javascript isn't my strong suit at the moment. My issue is that I have a multi-component SVG element. It is inline in the HTML and within a section tag. There is also a set of text elements in the section above the SVG. What I am trying to make happen is that when a portion of the SVG is hovered, the corresponding text element and the hovered SVG piece both change color. Vice versa if the text element is hovered, the corresponding SVG piece will change color as well. <section> <h1>Section 1</h1><h1>Section 2</h1> <svg id="World_Map"...<path class="_russia_"...</svg> </section> It is probably important to note that the SVG has multiple paths with unique ID's and these are the pieces that I am trying to get working in this fashion.
Yes, without the SVG elements being siblings or ancestors to your text elements this is very difficult (if not impossible) to do with CSS. I have seen some pretty tricky and amazing things done with CSS selectors, though, so I wouldn't rule it out that someone more clever than me could get it to work. :) Anyway, I have a working example of what you asked for using JavaScript. It actually makes use of jQuery because there is the .hover() binding, which cleanly allows you to bind a single function to the mouseenter and mouseleave events simultaneously, and the .toggleClass() method, which will add a class to an element if it doesn't exist or remove the class from the element if it's already there. Since you did not post any functional code, here is a JSFiddle with my simple example. https://jsfiddle.net/davecripps/o6mwjokj/ $(function() { $("h1").hover(function() { $("#map" + $(this).attr("id").substring(4)).toggleClass("mapHover"); }); $("rect").hover(function() { $("#text" + $(this).attr("id").substring(3)).toggleClass("textHover"); }); }); .textHover, h1:hover { color: red; cursor: pointer; } .mapHover, rect:hover { fill: red; } <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <section> <h1 id="textRussia">Russia (yellow)</h1> <h1 id="textSpain">Spain (blue)</h1> <h1 id="textFrance">France (green)</h1> <svg width="340" height="100" viewbox="0 0 340 100"> <rect id="mapRussia" x="0" y="0" width="100" height="100" fill="yellow" /> <rect id="mapSpain" x="120" y="0" width="100" height="100" fill="blue" /> <rect id="mapFrance" x="240" y="0" width="100" height="100" fill="green" /> </svg> </section> You should be able to understand the methodology and apply to your code.
How to keep a constant font-size in svg
I'm new with SVG and I try to add some text in a shape that I created. I've done it like this : https://fiddle.jshell.net/30kL3mzt/ But the text in the SVG change with the polygone. Is it possible to keep a constant size of text? Or at least to control the size of letters? <div id="tab"> <div class='chevron'> <svg width="25%" height='100%' viewBox="0 0 20 20" preserveAspectRatio="none"> <polygon fill=steelblue stroke-width=0 points="0,0 2,10 0,20 18,20 20,10 18,0" /> <text x="0" y="10" font-family="Verdana" font-size="2" >I love SVG!</text> </svg> </div> </div> <div id="middle"> <svg width="25%" height='100%' viewBox="0 0 20 20" preserveAspectRatio="none"> <polygon fill=steelblue stroke-width=0 points="0,0 2,10 0,20 18,20 20,10 18,0" /> <text x="0" y="10" font-family="Verdana" font-size="2" >I love SVG!</text> </svg> </div>
Why do you need the textual content to be in the SVG if you don't want it to scale? Probably it's better to have the text outside and style it with CSS to be where you want it.
Instead of adding svg directly inside your HTML, why not use a font library like fontello/icomoon? I know for a fact, when you choose the same grid size for your icons you can scale up your icons separately from your text. This is because an icon from a font file uses CSS on the pseudo-elements :before and/or :after. Combined with line-height you have complete control on the size of an icon. => Line-height is best calculated by the height of the layer divided by the font-size. For example: 24px div / 20px text = 1.2 In my opinion you're too far off from an x-browser solution to your problem. convert your shapes into font library (import svg files) add the proper CSS from the download (or read the readme.txt) make sure to support .woff on the server use font icon classes where needed override the proper font-sizes to your need in CSS (there's your solution)
Using an SVG and Apply CSS from Stylesheet
So I've browsed several articles and questions here, but no holy grail. I have an external file icon.svg, and I want to use it in several HTML files and have a different fill and sizes for each use. I can't use <object> from what I gather since it doesn't allow for styles from CSS sheets unless you reference that sheet from the SVG file itself, which kind of defeats the entire purpose. The only way I found how to do this is like this: <svg class="icon"> <use xlink:href="icon.svg#symbolid"></use> </svg> And the CSS applies. But I can only seem to do it if I add symbol nodes in the SVG file and give them an ID, which I'd rather not do. Also, could it be that this might be not supported in all major browsers ? Any way to achieve this ? Update: Added tags for javascript/angularjs since the solution was JS based. (see answer)
OPTION 1 - Using generic css styles Personally I create several fill colours and simply apply the class to the svg where required. HTML <svg class="icon red"> <use xlink:href="icon.svg#symbolid"></use> </svg> CSS .icon{ fill:#000; } .red{ fill:#b00; } .blue{ fill:#ddf; } OPTION 2 - SVG's targeted by unique class If your svg has several paths you can target each using other classes. HTML <svg class="icon symbol"> <use xlink:href="icon.svg#symbolid"></use> </svg> CSS .icon{ fill:#000; height:20px; width:20px; } .symbol{ height:40px; width:40px; } .symbol .path1{ fill:#b00; } .symbol .path2{ fill:#ddf; } OPTION 3 - SVG's as background images DEMO To utilise svg's like images they can be targeted with css and even used as background images in css but each svg symbol would need to be a unique file. <div class="icon"></div> .icon{ display:block; height:20px; width:20px; background: url(icon.svg); background-size: 20px 20px; } To use the svg as different height and widths simply edit in css using additional classes to overwrite defaults using specificity: .svg40{ height:40px; width:40px; } .svg100{ height:100px; width:100px; } OPTION 4 - Inline Svgs (My recommendation) DEMO Place the svg file directly in your html to reduce http requests and improve control. HTML Place just after your body tag at the top of your html <div style="height:0;width:0;position:absolute;visibility:hidden;"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <symbol id="symbolid1" viewBox="0 0 64 64"> <title>symbol 1</title> <path ... /> </symbol> <symbol id="symbolid2" viewBox="0 0 64 64"> <title>symbol 2</title> <path ... /> </symbol> </div> Then you can call the svg's from anywhere using the svg's id. <svg class="icon"><use xlink:href="#symbolid"/></svg> CSS .icon{ display:inline-block; fill:currentColor; width:20px; height:20px; }
I ended up using <object> and manipulating it after the SVG was rendered, in a way that would help me change the styling. To anyone interested in the more technical details, I've written the process here in my blog. I've created a directive in Angular to handle it, but of course you don't have to use Angular and could take the relevant parts and use it however you want. Edit: Wrote a bower for it, you can get it here.