skip to Main Content

I’m using an SVG pre-provided to me, and defined using <defs> and <g> elements similar to that one below (I have removed most of the path elements content for simplicity):

<svg xmlns="http://www.w3.org/2000/svg"viewBox="0 0 96 96" fill="none">
  <defs>
    <path id="singlecolor" d="M94.9588 20.6182L86.2126 5.20824V5H84.9631H68.5119H66.6377L66.4295"/>
    <g id="multicolor">
      <path d="M48 73.2971L52.7543 81.8L57.6 90.3943H48H38.4L43.1543 81.8L48 73.2971Z" fill="#E92D78" />
    </g>
  </defs>
  <g id="multicolor-onLight">
    <use href="#multicolor"/>
  </g>
  <g id="multicolor-onDark">
    <use href="#multicolor"/>
  </g>
  <g id="singlecolor-onDark">
    <use href="#singlecolor"/>
  </g>
</svg>

Today, this SVG is served as a standalone file and rendered in an img tag, and the src attribute contains an anchor tag, such as src='myfile.svg#multicolor-onLight'. This "selects" what gets eventually rendered, in that case the path defined under then <g> with id "multicolor".

In the future, I would like to resuse the same SVG but inline in my code. Is there a way to reuse the same SVG code as inline SVG, and more specifically, how to select which <g> element will be rendered?

I’m putting the <svg> inline in a <div> tag and tried to set Ids on both, but that made no difference. Seems only the "first" defined path is rendered…

2

Answers


  1. Chosen as BEST ANSWER

    OK looks like I found a way to solve this. Posting here if that can be useful to someone else...

    So, in the example I posted, the SVG contains a group with the following Ids: multicolor-onLight, multicolor-onDark and singleColor-onDark. As mentioned, when the SVG is rendered via an img tag, the src of the image acts as a selector.

    When rendering inline, the solution I used is to run some JavaScript to "trim" all SVG>g with a different id than the one I'm looking for. The code looks like (searching for id multicolor-onDark in that example):

       let gSet = document.querySelector('svg>g')
       for (let i = 0; i < gSet.length; i++) {
         if (gSet[i].id !== 'multicolor-onDark') gSet[i].remove()
       }
    

    Of course this "destroy" the source SVG so it must be "reloaded" if a different id is to be selected. It can indeed be done conveniently by embedding this in a custom element.


  2. Create the inline SVG with your own native <my-svg> JavaScript Web Component,
    configurable with attributes, and you do not needs all those <defs>

    customElements.define("my-svg", class extends HTMLElement {
      connectedCallback(){
        this.style.display    = "inline-block";
        this.style.width      = "100px";
        this.style.background = "pink";
        this.innerHTML = 
              `<svg viewBox="0 0 96 96" style="vertical-align:top">
                <circle cx="50%" cy="50%" r="50%" 
                        fill="${this.getAttribute("fill") || "red"}"></circle>
              </svg>`
      }
    });
    <my-svg></my-svg>
    <my-svg fill="yellow"></my-svg>
    <my-svg fill="blue"></my-svg>

    Your id issue with multiple SVGs having the same id is because inline SVGs will use the first defined id on the page. (no different how getElementById finds the first id)

    To work around that

    • either create a unique id in the Web Component
    • or add an extra shadowRoot to your Web Component to encapsulate all content.

    For both see: Is there a possibility to use a dynamic id in SVG fill=url(#)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search