gulp-stacksvg
v6.1.1
Published
The gulp plugin to combine svg files into one using the stack method.
Downloads
391
Maintainers
Readme
gulp-stacksvg
The gulp plugin to combine svg files into one using the stack method.
Installation
pnpm add -D gulp gulp-stacksvgUsage
Add the following to your gulpfile.js:
import { stacksvg } from "gulp-stacksvg"
import { dest, src } from "gulp"
export function createStack () {
return src(`./src/shared/icons/**/*.svg`)
.pipe(stacksvg())
.pipe(dest(`./dist/shared/icons`))
}To combine all icons from ./src/shared/icons/ into the ./dist/shared/icons/stack.svg run:
pnpm gulp createStackFragment names
Every icon keeps its own svg element inside the stack, named after the path of the source file relative to the directory the icons were read from:
- the extension is dropped,
- the directory separators become underscores,
- the whitespace characters become hyphens.
So ./src/shared/icons/social/like me.svg becomes social_like-me, and the fragment is referenced as ./dist/shared/icons/stack.svg#social_like-me.
Two icons whose paths collapse to the same name — social/like.svg and social_like.svg, for instance — abort the build, since the stack has no way to tell such fragments apart.
Identifiers used inside an icon are renamed to <fragment name>_<number>, so that icons declaring the same gradient, mask or filter stay independent once stacked. Do not rely on these from the outside: the numbering follows the document order of the icon and shifts whenever the icon changes.
Why a stack?
Unlike all other methods for assembling a sprite, the stack does not limit us in choosing how to insert a vector into a page. Take a look at the results of different ways to display fragments of different types of sprites.
We can use the stack in all four possible ways:
in markup:
- in
srcofimgtag — static, - in the
hrefof theusetag — with the possibility of repainting,
- in
in styles:
- in
url()propertiesbackground— static, - in
url()propertiesmask— with the possibility of repainting.
- in
Demo page to prove it.
Stack under the hood
This method was first mentioned in a Simurai article on April 2, 2012. But even it uses unnecessarily complex code transformations.
This can be done much easier. In general, the stack is arranged almost like a symbol sprite, but without changing the icon tag (it remains the svg tag, as in the original icon files) and with the addition of a tiny bit of style.
<svg xmlns="http://www.w3.org/2000/svg">
<style>:root svg:not(:target) { display: none }</style><svg id="sun" viewBox="0 0 24 24">
<!-- Inner code of sun icon -->
</svg><svg id="heart" viewBox="0 0 24 24">
<!-- Inner code of heart icon -->
</svg><svg id="thumbup" viewBox="0 0 24 24">
<!-- Inner code of thumbup icon -->
</svg></svg>The magic is in the stack inner style, which shows only the fragment requested by the link, hiding everything else:
:root svg:not(:target) { display: none }And now the icons from the external sprite are available in the styles
<button class="button button--icon_heart" type="button">
<span class="visually-hidden">Add to favorites</span>
</button>.button {
display: inline-flex;
align-items: center;
gap: 0.5em;
&:hover {
--fill: red;
}
&::before {
content: "";
width: 1em;
height: 1em;
/* icon shape */
mask: var(--icon) no-repeat center / contain;
/* icon color */
background: var(--fill, orangered);
}
&:where(.button--icon_heart) {
--icon: url("../icons/stack.svg#heart");
}
}For an icon inserted via mask, simply change the background. Moreover, unlike use, you can draw anything in the background under the mask, for example, a gradient.
