1

I would like to use SVG icons in my websites, and I know using <image> will limit my ability to change the SVG properties (for example, I can't change the fill color on hover).

So I found the method of in-line SVG, which seems to allows better manipulation. But gut feeling tells me that putting SVG drawing data into HTML file will create maintainability problem in the future.

I am trying to find a method where I can...

  1. Save my svg in another external file
  2. Call that svg from that file to my html file
  3. The html file will still be able to change the fill color.

Is this possible? And if yes, what is the keyword I should be looking for?

  • related: https://stackoverflow.com/a/61373740/8620333 – Temani Afif Jan 29 '21 at 08:16
  • The two most recent answers on [link]https://stackoverflow.com/questions/4906148/how-to-apply-a-style-to-an-embedded-svg may be helpful. They inject the svg at run time so you get better manipulation but you don't clutter up your HTML source for your maintainers. – A Haworth Jan 29 '21 at 08:17

2 Answers2

2

It depends on the programming language you use.

  • If you include an HTML file with (iframe), you cannot do what you want.

  • If you include a PHP file with (include) it will work the way you want.

For example:

index.php include to a svgs.php file.


However, you may want to consider creating an icon file with SVG Sprites. [See]

So you can load and recolor multiple icons from a single ".svg" file using short commands like below.

Remember: This technology does not support some SVG features such as Gradient. [1] [2]

<svg viewBox="0 0 24 24" class="icon">
  <use href="#foo"></use>
</svg>

<svg viewBox="0 0 24 24" class="icon">
  <use href="#bar"></use>
</svg>

Automatic SVG sprite generator tool: https://svgsprit.es/


Finally, you can use 3rd part scripts such as SVG injectors.

enter image description here

BOZ
  • 2,731
  • 11
  • 28
0

As stated by others you can dynamically load the svg into the document and access all of the elements of the svg via the html DOM. Here is how I have done it. You will see an insane line in here that looks like a inline SVG but don't worry you can replace it with an valid uri that points at an svg file. I only included the svg inline as a test so that it would work here without running into CORS problems with fetch.

Replace data-url with your uri

async function onload(){
    const data=document.querySelector("#svgContainer");
    let svgContainer=data;
    let urlSvg=data.dataset.url;
    await fetch(urlSvg)
        .then(r=>r.text())
        .then(t=>{svgContainer.innerHTML=t})
        .catch(e=>console.log(e));
    let newsvg=svgContainer.firstChild;
    newsvg.setAttribute("id","newsvg");
    newsvg.setAttribute("width","32px");
    newsvg.setAttribute("height","32px");
}   
onload();
#newsvg{
    animation: test 1s linear 0s infinite;
}
@keyframes test{
    0% {transform:translate(0%,0%);}
    20% {transform:translate(70%,0%);}
    80% {transform:translate(0%,70%);}
    100% {transform:translate(0%,0%);}
}
<div id="svgContainer" data-url="data:image/svg+xml,%3Csvg%20class=%22sIcon%22%20viewBox=%2210%20-6%201%2080%22%20xmlns=%22http://www.w3.org/2000/svg%22%3E%20%3Cg%3E%20%3Ccircle%20fill=%22rgb(255,0,0,1)%22%20transform=%22translate(0%200)%22%20cx=%2210%22%20cy=%2210%22%20r=%2210%22/%3E%20%3Ccircle%20fill=%22rgb(0,255,0,1)%22%20transform=%22translate(0%2024)%22%20cx=%2210%22%20cy=%2210%22%20r=%2210%22/%3E%20%3Ccircle%20fill=%22rgb(0,0,255,1)%22%20transform=%22translate(0%2048)%22%20cx=%2210%22%20cy=%2210%22%20r=%2210%22/%3E%20%3C/g%3E%20%3C/svg%3E"></div>