5

I am building a web component that renders svg icons onto the page in Shadow Dom. i.e.

<ba-icon i="airplane"></ba-icon>

I have an external svg sprite file, that has a ton of SVG icons in it.

The internals of the web component render the following into Shadow Dom:

<svg>
    <use xlink:href="i.dist.svg#i-airplane"></use>
<svg>

Everything is correctly rendering on the screen, but I am after some information that is embedded inside of the SVG, specifically the information contained in the viewbox, (for example: viewBox="0 0 32 32").

I know that what is rendered in the use is input into the Shadow Dom as well. But I am trying to find another way of obtaining the information embedded into the use. I tried to ajax the contents of the svg, but this is turning into a big problem for multiple icons on the page since each instance of the web component is now making that call. How else could I do this?

For reference:

enter image description here

KevBot
  • 17,900
  • 5
  • 50
  • 68
  • You can always get these infos from the original SVG you into you custom element. – Supersharp Jul 15 '16 at 07:53
  • @Supersharp, I'm not sure I follow. When you put an svg on the page that references an external svg (`/images/sprite.svg#some-icon`), the browser treats it as an external resource and will request that "sprite" file in the same manner as any image. The only difference is that is pulls a specific symbol from the sprite file via the ID (#some-icon). I'm not inlining the original svg into the page. – KevBot Jul 15 '16 at 14:57

2 Answers2

3

Actually there are manys ways to acheive this, depending of the structure of the SVG file you use, and what you want to do.

With SVG sprites as an external file, you can take profit of the HTML Imports technology to parse the file:

<head>
...
  <link id="ic" rel="import" href="i.dist.svg">

  <script>
    document.registerElement( "ba-icon", { 
        prototype:  Object.create( HTMLElement.prototype, {
            createdCallback: {
                value: function () 
                {
                    var name = "i-" + this.getAttribute( 'i' )
                    var sh = this.createShadowRoot()
                    sh.innerHTML = '<svg><use xlink:href="i.dist.svg#' + name + '"/>'
                    this.setAttribute( "i-viewBox", ic.import.querySelector( 'svg#' + name ).getAttribute( "viewBox" ) )
                }
            }
        } )
    } )
  </script>
</head>

The SVG file is not imported twice because it is cached by the browser.

Note: This solution (using <use>) may not be the fastest but it is the simplest to code, and to understand. It depends on what you really want to do with the attributes (and when).

Supersharp
  • 29,002
  • 9
  • 92
  • 134
  • This worked really well, great idea! I hadn't considered importing the `i.dist.svg` file. But doing so, allowed me to get the viewBox data so that I could parse some dimensions. And since the sprite file now essentially is a document that I can query, I was able to use child nodes of the symbol so that I could avoid using `use`. – KevBot Jul 15 '16 at 17:31
  • Yes I think using the child nodes of the symbol is a better approach, too. – Supersharp Jul 16 '16 at 00:04
0

HTML Imports removed from Chrome 80.

Use alternative like Fetch().

Jangya satapathy
  • 866
  • 8
  • 20