⚛ Light-weight Preact SVG icon wrapper
MIT License
A Light-weight Preact SVG icon wrapper
npm add preact-svg-icon
PersonIcon.jsx
import toSvgIcon from 'preact-svg-icon';
// provide a SVG file and fragment id to use as icon
export default toSvgIcon('/person.svg', 'fragment-id');
Using the icon:
import PersonIcon from './PersonIcon';
function MyPage() {
return <PersonIcon
className="css-class-1 css-class-2"
color="red"
size={16}
style={{ textAlign: 'center' }}
title="Profile settings"
titleId="profile-icon-title"
>;
}
npm ci
npm start
# Watch changes on a new terminal
npm run example:watch
Many SVG icon solutions converts SVGs to JSX when creating their icon components.
This means the entire SVG is now inside your javascript file. This increases the parse and execute time. If the SVG were to be already in the HTML or downloaded by browser (like an image) then that would be more ideal.
The icons are potentially repeated across JS bundles (e.g. if code splitting is used). It would be nicer if browser could cache the SVGs across pages like how regular images can be cached.
There are couple of solutions to this. One such solution that allows browsers to cache the icons is by having the icon as an .svg
file, with an id
on the <svg>
element or on the individual elements inside of the svg tag (also known as "SVG sprite") and then at the place where you want to use the icon, use a svg <use>
tag pointing to the SVG file via a "fragment URL" (fancy way of saying <url>#<id>
). e.g:
<svg>
<use href="/path/to/icon.svg#id">
</svg>
This helps us in the following ways:
<use>
tag is bundled across pages; which is extremely small.fill
color. By default if you set fill="currentColor"
on the SVG, then it will inherit the text color from parent. It can't do advanced styling, animations etc like an inline SVG. But for most icons, this is an acceptable trade-off. There are advanced progressive enhanced ways of converting the tag into inline SVG via JS, but I won't delve into that here.rel="preload"
or by having some of the SVGs sprited in the HTML itself (when referencing them you can skip the URL part and keep only the fragment part - <use href="#id">
). SVG sprite example:
<svg width="0" height="0" style="display: none">
<symbol id="icon1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M502.3 ..."></path>
</symbol>
<symbol id="icon2" ...>
...
</symbol>
</svg>
<!-- Usage: How to use an SVG already in HTML -->
<svg>
<use href="#icon1">
</svg>
If you have many icons to add fragment ids to, then this repo provides a node.js script inside utils/
directory to add an id
to a directory full of svg files. Note: It will also remove fill attribute from <svg>
element
node utils/add-svg-id.js myicon.svg
# or full directory
# node utils/add-svg-id.js .