- Using SVG can be tricky, so many ways to use SVG, styling limitations, CORS issues, bad browsers support, etc. svgSprite is a selection of the best hacks and techniques available.
- Handle inserted elements at any time, mandatory for SPA and website injecting content in pages.
- Easiest way to migrate from webfont to SVG icons set, replacing any icon systems with SVG sprite without markup change.
By using a simple data-svg attribute in your markup:
<i data-svg="icon-a"></i>…
<i data-svg="icon-z"></i>…
and a terse js API:
svgSprite({source: 'https://example.com/assets/icons.svg'})
You'll get the SVG sprite injected in DOM and single SVGs pointing to SVG sprite symbols:
<i data-svg="icon-a"><svg role="presentation"><use xlink:href="#icon-a"/></svg></i>…
<i data-svg="icon-z"><svg role="presentation"><use xlink:href="#icon-z"/></svg></i>…
<svg dispay="none" data-source="https://example.com/assets/icons.svg">
<symbol id="icon-a">…</symbol>…
<symbol id="icon-z">…</symbol>…
</svg>
Alternativelly, you can inline SVGs (using an external sprite) already in DOM:
<svg><use xlink:href="https://example.com/assets/graphics.svg#logo"/></svg>…
<svg><use xlink:href="https://example.com/assets/graphics.svg#worldmap"/></svg>…
By simply calling:
svgSprite.inline()
Again, you'll get single SVGs pointing to symbol in a unique inlined SVG sprite:
<svg><use xlink:href="#logo"/></svg>…
<svg><use xlink:href="#worldmap"/></svg>…
<svg dispay="none" data-source="https://example.com/assets/graphics.svg">
<symbol id="logo">…</symbol>…
<symbol id="worldmap">…</symbol>…
</svg>
- Watch inserted nodes (looking for data-svg / SVG with external ressource), then inject or swap SVGs pointing to inlined sprite very efficiently (use events, no polling).
- Targets specifc 'elements' using a simple selector or a node list.
- Use as many SVG sprites as you want.
- Cache and deduplicate requests of external SVG sprites sources.
- Accepts URL and SVG markup sources, caching may be done with network and/or local storage.
- Use semantic and accessibility attributes to hide sprites and decorate injected / swapped SVGs.
- May be used at any time even before DOM is loaded.
- Allows advanced customization with a simple callback:
- Specify 'viewbox' attribute to size and pad SVG symbols.
- Keep short meaningful names in data-svg attribute with prefixed/suffixed ids in SVG sprite.
- Rename / alias some elements in an symbol or icon set.
- Use custom markup even without data-svg attribute.
- Zero dependencies.
- Only 1.6Kb minified & gzipped.
- UMD loader with named AMD definition included.
Targets evergreen browsers only, but successfully tested (some demo animation may not work thought) via Browserling & BrowserStack with Chrome 21+, Firefox 16+, IE 10+, Opera 16+, Safari 7.1, Safari iOS 9 & Android 4.4.
Ugly demo with helpful commented sources.
npm i
<script src="https://cdn.rawgit.com/adriengibrat/svgSprite/v1.2.0/svgSprite.min.js"></script>
Download the svgSprite.min.js file and add it to your project.
svgSprite({
source: url || markup
, elements: selector || collection // optional
, before: function (svg, id, use, element, sprite, source) { // optional
// 'svg' is the SVG element before it is injected
// 'id' is the id used by default as fragment in xlink:href attribute (e.g. data-svg value)
// 'use' is a utility function to optionaly change the SVG use tag xlink:href attribute
// 'element' is the element where the SVG will be injected
// 'sprite' is the SVG sprite already injected in DOM
// 'source' is the source (URL or markup) of the SVG sprite
// return false to avoid injecting the SVG in the element
}
})
// returns a function (see below)
svgSprite.inline({
elements: selector || collection // optional
, before: function (svg, id, sprite, source) { // optional
// 'svg' is the SVG element pointing to external resource
// 'id' is the id used as fragment in xlink:href attribute
// 'sprite' is the SVG sprite already injected in DOM
// 'source' is the source URL of the SVG sprite
// return false to avoid changing the SVG use tag xlink:href attribute
}
})
// returns a function (see below)
The function returned by svgSprite()
and svgSprite.inline()
always returns the list of SVGs already processed.
N.B.: all process are async, the lists may contain null values:
- when the SVG is not injected yet (sprite load is pending).
- when the SVG or its use tag have been removed from DOM.
- when the SVG injection has been prevented (before() returning false).
const done = svgSprite({ source: 'https://example.com/sprite.svg' }) // or svgSprite.inline()
…
// prevents new elements to be proccessed
done(true)
// and remove all injected SVGs
.forEach(svg => svg && svg.remove())
When 'elements' is not a collection, calling the function returned with a truthy argument also pevents the new elements injected from being processed.
npm install
npm start
npm run size
- The demo needs a graphic designer, help wanted ;)
- Create a simple tool to generate SVG sprite with symbols & views that allow SVG external link, inlining, fragment identifiers to use as img src / css background, nice previews, clean source, with easy symbol discovery and visualisation.
You may use this software under the WTF Public License.
- Adrien Gibrat – https://github.com/adriengibrat
Thanks to:
- Jonathan Neal's svg4everybody insprired me and was great source of useful information.
- Iconic SVGInjector for the cache & inject external SVG then swap elements lead.
- Sara Soueidan's great articles about SVG, very detailed and inspiring.
- Daniel Buchner's post & David Walsh's article for, respectively, inventing & spreading great hacks.
- Iconic Icons, Material icons, Evil icons, Fontastic icons & Octicons used in the demo via Jsdelivr & Rawgit.
You should use symbol
tags and always define custom viewboxes:
<symbol id="asset-id" viewBox="left top width height">
<path …/> …
</symbol>
You may add usefull descriptive tags and aria attributes.
<defs role="presentation">
<symbol id="asset-id" viewBox="left top width height" aria-labelledby="title">
<title>Meaningful name</title>
<path …/> …
</symbol>
<symbol id="another-id" viewBox="left top width height" aria-labelledby="title desc">
<title>Another name</title>
<desc>Longer description</desc>
<path …/> …
</symbol>
…
</defs>
When inlined in HTML5 xmlns
attributes are useless, but you should keep them on your sprite SVGs if they are consumed by another way (via css by example).
<svg xmlns="http://www.w3.org/2000/svg"[ xmlns:xlink="http://www.w3.org/1999/xlink"]>
…
</svg>
Use the great SVGO cli:
npm i -g svgo
svgo sprite.svg
Thanks to svg-sprite, it's quite simple:
npm i -g svg-sprite
svg-sprite --symbol --symbol-dest=. --symbol-sprite=sprite.svg svg/*.svg