Home > database >  Is there a way to both load an SVG-image by URL and be able to fill it with CSS color variables?
Is there a way to both load an SVG-image by URL and be able to fill it with CSS color variables?

Time:01-21

I'm building an editor where users can select an SVG from our CDN, and select its fill color. On the front-end I want to be able to render these SVG's in the color that's picked by the user, but this doesn't seem to be possible. Does anybody know any approaches I should try?

The data I get from the server is the following:

  • cdnURL: the URL from which the SVG should be loaded

  • fillColor: text corresponding to SCSS variables in our frontend. I have made utility classes for all colors to implement the fill-property:

    color__fill--black { fill: black; }
    

I have come across answers on this site that suggest changing the fill-property of the SVG-file, but this is not possible because I only have its source-URL on the CDN. I have also seen people suggest using CSS filters, but this does not solve my issue as the colors vary a lot, from black to blue to yellow to white.

CodePudding user response:

I will suggest that you load the selected SVG and insert it inline into an HTML element. Here I just use the fetch function. Basically my data URLs in the array could be replaced with ordinary URLs and the code will still work (running from a web server from the same domain).

There could be a number of different approaches to when it comes to the color. Here I change the content of a style element. Any element in the SVG will get the specified color.

const urls = [ 'data:image/svg xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAgMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI CiAgPHBhdGggZD0iTSA1IDAgTCAwIDUgTCA1IDEwIEwgMTAgNSBaIiAvPgo8L3N2Zz4=',
'data:image/svg xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAgMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI CiAgPGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIC8 Cjwvc3ZnPg=='
];

const container = document.getElementById('container');
const style = document.getElementById('style01');

document.forms.form01.img.addEventListener('change', e => {
  if(e.target.value){
    fetch(urls[e.target.value]).then(res => res.text()).then(text => {
      container.innerHTML = text;
    });
  }
});

document.forms.form01.color.addEventListener('change', e => {
  style.textContent = `#container * {fill: ${e.target.value};}`;
});
#container {
  width: 200px;
}
<style id="style01">#container * {fill: #1a5fb4;}</style>
<form name="form01">
  <select name="img">
    <option>Select an SVG</option>
    <option value="0">SVG 1</option>
    <option value="1">SVG 2</option>
  </select>
  <input name="color" type="color" value="#1a5fb4" />
</form>
<div id="container"></div>

CodePudding user response:

Easy does it, create a native javascript <load-svg> Web Component.

  • loads external SVG files
  • assigns its to a shadowDOM innerHTML
  • appends all your <style> elements

<load-svg src="//svg-cdn.github.io/heart.svg">
  <style>
    svg { height: 180px  } path:nth-child(2n 2) { fill: red }
  </style>
</load-svg>

<load-svg src="//svg-cdn.github.io/heart.svg">
  <style>
    svg { height: 180px } path:nth-child(3n 2) { fill: yellow }
  </style>
</load-svg>

<load-svg src="//svg-cdn.github.io/heart.svg">
  <style>
    svg { height: 180px } path:nth-child(3n 1) { fill: blue }
  </style>
</load-svg>

<script>
  customElements.define('load-svg', class extends HTMLElement {
    async connectedCallback() {
      this.attachShadow({mode:"open"})
          .innerHTML = await (await fetch(this.getAttribute("src"))).text();
      this.shadowRoot.append(...this.childNodes);
    }
  });
</script>

  • Related