Templarian / MaterialDesign

✒7000+ Material Design Icons from the Community
https://materialdesignicons.com
Other
11.02k stars 723 forks source link

Single SVG using <symbol> #4196

Open Crissov opened 5 years ago

Crissov commented 5 years ago

I somehow expected MaterialDesign-SVG to include a single SVG file containing all icons, but, via #3516, I found mdi.svg in MaterialDesign-Angular-Material instead. However, that file currently looks like this:

<svg>
  <defs>
    <svg id="{MDI name}" viewBox="0 0 24 24"><path d="{path data}"/></svg>
    ...
  </defs>
</svg>

I expected something more akin to this:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>
    <symbol id="{MDI name}" viewBox="0 0 24 24"><path d="{path data}"/></symbol>
    <!-- or -->
    <symbol id="{MDI name}" width="24" height="24"><path d="{path data}"/></symbol>
    <!-- or even -->
    <symbol id="{MDI name}" width="24" height="24" viewBox="0 0 24 24"><path d="{path data}"/></symbol>
    ...
  </defs>
</svg>

or, since the symbols are uniform, simply

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
     viewBox="0 0 24 24" width="24" height="24">
  <defs>
    <symbol id="{MDI name}"><path d="{path data}"/></symbol>
    ...
  </defs>
</svg>

Could this be changed or should such a file be added separately?

Templarian commented 5 years ago

Assuming you're using some kind of build tool that detects use tags and extracts just the icons you're using. If we put all 3.7k icons into a single file it would be rather large in size.

Is this to support a specific tool/framework?

By the way we highly recommend using @mdi/js for javascript developers as you get tree shaking for free.

MrGrigri commented 5 years ago

I think it would be nice if we had a .mdi file that had an array of icon names that could be used with a Webpack plugin to generate an SVG with the symbols and place it at the start of the body tag in the index.html file.

.mdi

{
  "icons": [
    "account"
    ...
    "zodiac-scorpio"
  ]
}

index.html

...
<body>
  <!-- injected here via Webpack -->
  <svg  version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" display="none" aria-hidden="true" width="0" height="0" hidden>
    <defs>
      <symbol id="mdi-sprite-account" viewBox="0 0 24 24">
        <path d="..."/>
      </symbol>
      <symbol id="mdi-zodiac-scorpio" viewBox="0 0 24 24">
        <path d="..."/>
      </symbol>
    </defs>
  </svg>
  ...
</body>

And then when using the SVG later in the page

...
<svg width="24" height="24"><use href="#mdi-sprite-account></use></svg>
...

This could be simplified by creating a component with Angular or React that generates the using SVG by just passing the icon property with the name of the icon like this:

<mdi-svg icon="account></mdi-svg>
Templarian commented 5 years ago

If you're using a webpack plugin at that point you can just replace the <use href="#mdi-sprite-account></use> and assume a peerDependency of @mdi/svg and inject the icons into the <svg> tags. Pretty easy plugin to write.

My problem with this is one should use more framework friendly methods to consume the icons like @mdi/js. I agree if you're building a static website we could provide a quick webpack plugin.

MrGrigri commented 5 years ago

The only problem with that is bloat. If I'm using account throughout my application, a single reference is more performant.

Templarian commented 5 years ago

Does anyone know how use statements work with shadow dom? Are there any gotchas that come with this? Like I assume if it's in index.html it won't see it right?

MrGrigri commented 5 years ago

From what I understand it wouldn't work. That is the only caveat to using the use statement. It would be a clone of a clone.

Templarian commented 5 years ago

Lets go in with the assumption anyone using any of our tooling is working with Shadow Dom.

If one is using the @mdi/js package it reference in a way that doesn't duplicate. So keep that in mind.

MrGrigri commented 5 years ago

Here is a StackBlitz example of an SVG inside of a cloned custom element. Unless I'm doing things wrong, it doesn't work. The SVG use statement creates a closed clone as opposed to an open clone. Idk if this can be changed.

Crissov commented 5 years ago

Font Awesome offers such SVG “sprite sheets”, so some people apparently have a use for them.

Templarian commented 5 years ago

@Crissov Unfortunately that approach encourages people to load all the icons. That would not be ideal as we reach 4k icons. I'm fine documenting an approach for this and generating an SVG file, but would not add it to the @mdi/ org namespace.

Webfont has the same issue and we are constantly trying discourage usage of it in the docs.

Crissov commented 5 years ago

Well, mdi.svg does already exist for Angular. Itʼs certainly not something authors should expose to users in production, but a single file can be helpful in design and development.

PS: The original Google distribution also provides spritesheets for icon categories, using <symbol>.

1anc commented 5 years ago

@Templarian An iconfont plugin that I use with Sketch (https://github.com/keremciu/sketch-iconfont) requires the SVG sprite to install the font. Could you please add it back?

Thanks

spudatron commented 4 years ago

@Templarian An iconfont plugin that I use with Sketch (https://github.com/keremciu/sketch-iconfont) requires the SVG sprite to install the font. Could you please add it back?

Thanks

I am the same as @112358z, I can upgrade to the latest version in Sketch since this plugin only supports the sprite.

petrprikryl commented 4 years ago

@Crissov Unfortunately that approach encourages people to load all the icons. That would not be ideal as we reach 4k icons. I'm fine documenting an approach for this and generating an SVG file, but would not add it to the @mdi/ org namespace.

Webfont has the same issue and we are constantly trying discourage usage of it in the docs.

Could it be resolved by this https://github.com/JetBrains/svg-sprite-loader?