SVGs from an external source can be rendered via <img>
tags, but this has multiple drawbacks: you can't customize the fill, use CSS variables, or use focus/hover states.
SVG loader is a simple JS code you can include that fetches SVGs using XHR and injects the SVG code in the tag's place, giving you best of both worlds: externally stored SVGs (e.g, on CDN) and inline SVGs.
It's super-tiny, works well with frameworks and has minimal to no impact on performance.
SVG Loader is designed to be plug and play. Hence, all you need to is to include the loader JS anywhere in your code, and then start using the code like this:
<!--
Include this script anywhere in your code, preferably <HEAD> so
icons can be fetched faster.
-->
<script type="text/javascript" src="svg-loader.min.js" async></script>
<!-- Use an external SVG -->
<svg data-src="https://unpkg.com/@mdi/svg@5.9.55/svg/star.svg" width="50" height="50" fill="red"></svg>
<svg data-src="https://unpkg.com/@mdi/svg@5.9.55/svg/heart.svg" width="50" height="50" fill="red"></svg>
<svg data-src="https://unpkg.com/@mdi/svg@5.9.55/svg/cog.svg"
width="50"
height="50"
fill="currentColor"
style="color: purple;"></svg>
Note: Because SVG Loader fetches file using XHRs, it's limited by CORS policies of the browser.
So you need to ensure that correct Access-Control-Allow-Origin
headers are sent with the file being served or that the files are hosted on your own domain.
The library is framework/platform agnostic. You should be able to use it in React, Vue.js and others as long as you're using the correct attributes.
npm install external-svg-loader
Then, in your app, require/import external-svg-loader
anywhere. Here's an example:
import React from "react";
import ReactDOM from "react-dom";
import "external-svg-loader";
class App extends React.Component {
render() {
return (
<svg
data-src="https://s2.svgbox.net/materialui.svg?ic=mail"
fill="currentColor"
width="50px"
height="50px"
style={{
color: "red"
}}
/>
);
}
}
ReactDOM.render(<App />, document.getElementById("container"));
SVG loader can also be included via unpkg CDN. Example:
<script type="text/javascript" src="https://unpkg.com/external-svg-loader@1.3.1/svg-loader.min.js" async></script>
By default, the XHR response is cached for 24 hours, so that any subsequent loads are instantenous. You can disable this behavior by passing data-cache="disabled"
. You can also modify
the caching period by passing number of seconds. Example:
<svg data-src="https://unpkg.com/@mdi/svg@5.9.55/svg/heart.svg" width="50" height="50" data-cache="604800"></svg>
<svg data-src="https://unpkg.com/@mdi/svg@5.9.55/svg/heart.svg" width="50" height="50" data-cache="21600"></svg>
<svg data-src="https://unpkg.com/@mdi/svg@5.9.55/svg/heart.svg" width="50" height="50" data-cache="disabled"></svg>
SVG format supports scripting. However, for security reasons, svg-loader will strip all JS code before injecting the SVG file. You can enable it by:
<svg data-src="https://unpkg.com/@mdi/svg@5.9.55/svg/heart.svg" data-js="enabled" width="50" height="50" fill="red"></svg>
To prevent conflicts between conflicting identifiers of different SVGs, svg-loader scopes the identifiers and styling rules, by adding prefixes.
You can disable this behavior by:
<svg data-src="https://unpkg.com/@mdi/svg@5.9.55/svg/heart.svg" data-unique-ids="disabled" width="50" height="50" fill="red"></svg>
<svg data-src="https://unpkg.com/@mdi/svg@5.9.55/svg/heart.svg" data-css-scoping="disabled" width="50" height="50" fill="red"></svg>
You can also lazy load icons by using data-loading=lazy
. This will make icon not load until it's about to enter the viewport. For lazy loading, external-svg-loader
uses Intersection Observer API.
<svg data-src="https://unpkg.com/@mdi/svg@5.9.55/svg/heart.svg" width="50" height="50" data-loading="lazy"></svg>
You can specify a fallback icon, using data-fallback='<svg>...</svg>'
. It will ensure, an icon will be displayed by default if something went wrong during the downloading of the first icon.
<svg data-src="https://unpkg.com/@mdi/svg@5.9.55/svg/heart.svg" width="50" height="50" data-fallback='<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="50"/></svg>'></svg>
You will need to pass the fallback icon SVG, as a string to the data-fallback
attribute. You can easily import an .svg
in react using the following lines:
import React from "react";
import { renderToStaticMarkup } from "react-dom/server";
import {ReactComponent as Icon} from './default-icon.svg';
var defaultIcon = renderToStaticMarkup(<Icon/>);
export const MyComponent = (props) => {
return (<svg
data-src="https://unpkg.com/@mdi/svg@5.9.55/svg/heart.svg"
width="50"
height="50"
data-fallback={defaultIcon}></svg>
)
}
MIT