gulp-stacksvg

The gulp plugin to combine svg files into one using the stack method.


Keywords
gulpplugin, svg, icon, stack, sprite, gulp-plugin
License
MIT
Install
npm install gulp-stacksvg@3.0.0

Documentation

gulp-stacksvg

Test Status License: MIT NPM version Vulnerabilities count

Combine svg icon files into one with stack method.

Installation

npm install gulp-stacksvg --save-dev

Usage

The following script will combine all svg sources into single svg file with stack method.

import { stacksvg } from "gulp-stacksvg"
import gulp from "gulp"

const { src, dest } = gulp

function makeStack () {
	return src(`./src/icons/**/*.svg`)
		.pipe(stacksvg({ output: `sprite` }))
		.pipe(dest(`./dest/icons`))
}

Avalable options

Option Description Default
output Sets the stack file name. Accepts values ​both with and without the .svg extension. stack.svg
separator Replaces the directory separator for the id attribute. _
spacer Joins space-separated words for the id attribute. -

Inlining stacksvg result into markup

You just don't have to want it.

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 src of img tag — static,
    • in the href of the use tag — with the possibility of repainting,
  • in styles:
    • in url() properties background — static,
    • in url() properties mask — with the possibility of repainting.

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 remain 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" xmlns:xlink="http://www.w3.org/1999/xlink">

	<style>
		:root { visibility: hidden }
		:target { visibility: visible }
	</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:

  • :root { visibility: hidden } — hides the entire contents of the stack,
  • :target { visibility: visible } — shows only the fragment that is requested by its link.

And now the icons from the external sprite are available in the styles heart

<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;
}

.button--icon_heart {
	--icon: url("../icons/stack.svg#heart");
}

.button:hover {
	--fill: red;
}

.button::before {
	content: "";
	width: 1em;
	height: 1em;
	/* icon shape */
	mask: var(--icon) no-repeat center / contain;
	/* icon color */
	background: var(--fill, orangered);
}

⚠️ Note:
We still need the autoprefixer for the mask property.

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.