README
SVG icon sprite component for Angular 12
This library provides both a solution for generating SVG sprites and a module for including them.
Demo
Try out the ng-svg-icon-sprite demo
Use Cases
- include single-color icons from a sprite
- fill and scale icons dynamically via CSS (i.e. hover, focus effects)
- meet accessibility requirements for inline SVGs
Installation
After installing the package as dependency you can import it into
any application’s app.module.ts
by simply including it in its @NgModule
imports array:
import { IconSpriteModule } from 'ng-svg-icon-sprite'; // <-- here
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
IconSpriteModule // <-- here
],
bootstrap: [AppComponent]
})
export class AppModule { }
Usage
To use your SVGs from a sprite you need to:
- Convert your SVG icons into a sprite using a script
- Include the
svg-icon-sprite
component with the sprite path, and the icon name
Step 1: Generate the sprite
First add the library for sprite generation svg2sprite as a devDependency:
"devDependencies": {
"svg2sprite-cli": "^2.0.1"
}
Each time you add an icon, you need to run the script generating the sprite. You might want to add it to your npm scripts:
"scripts": {
"generate:svg-sprite": "svg2sprite ./src/assets/icons ./src/assets/sprites/sprite.svg --stripAttrs fill --stripAttrs stroke --stripAttrs id"
}
now execute the script:
npm run generate:svg-sprite
Note: only if the fill and stroke attributes are removed, the SVG can be styled via CSS. If don't need to apply color changes on your icons, go for the multi-color pattern described below
The script will take all SVG icons under src/app/assets/icons
and create a sprite SVG into
src/app/assets/sprites
using the svg symbols technique:
app
└── assets
└── icons (icons source)
└── icon-1.svg
└── icon-2.svg
└── sprites (sprite destination)
└── sprite.svg
Step 2: Use the component
Now you can include icons by using the svg-icon-sprite
component directive:
<!-- include the icon named 'cart' -->
<svg-icon-sprite
[src]="'assets/sprites/sprite.svg#cart'"
[width]="'22px'"
[classes]="'my-icon-class'"
></svg-icon-sprite>
Having a dynamic icon name:
<svg-icon-sprite [src]="'assets/sprites/sprite.svg#' + iconName"></svg-icon-sprite>
Options
src
- icon source name, the syntax ispath/file#icon
wherepath
is relative to app folder,file
is the name of the sprite andicon
is the filename of the svg icon.width
optional - width of the svg in any length unit, i.e.32px
,50%
,auto
etc., default is100%
height
optional - the height of the svg in any length unit, if undefined height will equal the widthclasses
optional - class name(s) for this icon, default isicon
viewBox
optional - define lengths and coordinates in order to scale to fit the total space available (use for scaling)preserveAspectRatio
optional - manipulate the aspect ratio, only in combination withviewBox
title
- optional - text string that will be rendered into a title tag as the first child of the SVG nodeattribute
- optional - tuple or array of tuples containing key/value pair that should be added as an attribute on the SVG node, i.e."['aria-hidden', 'true']"
becomes<svg aria-hidden="true">
Styling
In order to change the icon color, add a CSS color
property to the component invoking svg-icon-sprite. The SVG component uses
the currentColor
value to pass the ancestor's color through to the SVG shapes:
/* host component styles */
color: red;
Advanced Configuration
Assets folder
If you have another asset folder structure, set your input and output path in the npm script:
svg2sprite sourcefolder destination/filename.svg
Scaling and Sizing
If your SVG does not scale like expected (i.e. it is cropped or larger than desired) it might be lacking a viewBox
.
You need to set the viewBox
attributes manually to match the size of the exported shape. A combination of the correct
viewBox
and width is required. Add the viewBox
attribute and decrease/increase the last 2 values:
<!-- i.e. lower '0 0 80 80' to '0 0 40 40' to scale up/down -->
<svg-icon-sprite
[src]="'assets/sprites/sprite.svg#star'"
[width]="'40px'"
[viewBox]="'0 0 80 80'"
></svg-icon-sprite>
See the viewBox example for further details. Still having trouble with scaling or sizing? Read this article about SVG scaling.
Dealing with multi color SVGs containing inline styles
If you wish use SVGs that contain inline styles (multi-color) that do not need to be overridden by CSS, provide a separate sprite file that keeps the stroke and fill attributes:
"scripts": {
"generate:svg-multicolor-sprite": "svg2sprite ./src/assets/svg-images ./src/assets/sprites/image-sprite.svg"
}
The generated sprite will preserve its original styles, but you won't be able to style it via CSS that easily (demo).
Setting a default sprite path for all icons
If your app uses one sprite source, you can set its path in your @NgModule
imports array:
imports: [
IconSpriteModule.forRoot({ path: 'assets/sprites/sprite.svg' })
]
You can now leave out the path and just provide the icon name (demo).
<svg-icon-sprite [src]="'star'"></svg-icon-sprite>
Doing so you will still be able to override the default path by using the full syntax for particular icons that should use a different sprite file.
Browser Support
- Chrome (63)
- Firefox (57)
- Safari 11
- Edge
IE 11 support was removed in version 1.10.
Accessibility
In order to support screen readers and make the icons meaningful, you can use following patters:
- add a
title
with descriptive text (demo) - optionally reference the title node using
aria-labelledby=”icon-title”
- optionally set the node's
role
to image (role=”img”
)
<svg-icon-sprite
[src]="'assets/sprites/sprite.svg#star'"
[title]="'Some title text'"
[attribute]="[['aria-labelledby', 'star-title'], ['role', 'img']]"
></svg-icon-sprite>
If you want to prevent the icon from being accessed by screen readers (i.e if you already have a descriptive text somewhere else),
set the attribute
of ['aria-hidden', 'true']
instead.
Or use combinations of several methods to achieve better results, like described in this article.
Compatibility
This library is optimized for Angular 12, for 11 use v. 1.10, for 10 use v. 1.9. If you combine multiple frameworks (i.e. React, Vue, etc.), it is recommended to use svg-icon-sprite web component instead!
Author & License
- Jan Suwart | MIT License