https://github.com/munawwar/preact-svg-icon
⚛ Light-weight Preact SVG icon wrapper
https://github.com/munawwar/preact-svg-icon
Last synced: 8 months ago
JSON representation
⚛ Light-weight Preact SVG icon wrapper
- Host: GitHub
- URL: https://github.com/munawwar/preact-svg-icon
- Owner: Munawwar
- License: mit
- Created: 2022-10-01T07:14:55.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2024-12-04T20:17:38.000Z (10 months ago)
- Last Synced: 2025-02-06T14:09:26.102Z (8 months ago)
- Language: JavaScript
- Homepage:
- Size: 62.5 KB
- Stars: 12
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# preact-svg-icon
A Light-weight Preact SVG icon wrapper
```sh
npm add preact-svg-icon
```## Usage
PersonIcon.jsx
```js
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:
```jsx
import PersonIcon from './PersonIcon';function MyPage() {
return ;
}
```## Run demo
```sh
npm ci
npm start
# Watch changes on a new terminal
npm run example:watch
```## What problem is this solving?
Many SVG icon solutions converts SVGs to JSX when creating their icon components.
1. This means the SVGs are now inside your javascript file. This increases the parse and execute time of your JS. It would have been better, if the SVGs were not in the JS and were already in the HTML or downloaded by browser (like an image).
2. The icons are potentially repeated across JS bundles / pages (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.
## Solution
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 `` 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 `` tag pointing to the SVG file via a "fragment URL" (fancy way of saying `#`). e.g:
```html
```
This helps us in the following ways:
1. **Less JS**: Very less SVG remains in the JS bundle. Also when page code splitting is used, only the base component used to generate the `` tag is bundled across pages; which is extremely small.
2. **Styleable**: Mostly styleable (*waves hand in the air*). It respects css `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, that is an acceptable trade-off. There are [advanced progressive enhanced ways](https://css-tricks.com/inline-svg-cached/) of converting the tag into inline SVG via JS, but I won't use those techniques here as I intend to keep this library small and simple.
3. **Cacheable**: The SVG files could be cached by browser now across pages (using Cache-Control HTTP headers, just like images, css or js files).
4. **Preloadable**: To avoid a "flash of blank space" on SVGs on the immediately visible area of a page on a page load, you could selectively preload some SVGs via link tag `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 - ``). SVG sprite example:
```html
...
```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 `` element
```sh
node utils/add-svg-id.js myicon.svg
# or full directory
# node utils/add-svg-id.js .
```## References
1. https://css-tricks.com/svg-sprites-use-better-icon-fonts/
2. https://css-tricks.com/accessible-svgs/