npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

postcss-svg-mask-image

v0.2.1

Published

PostCSS plugin for SVG mask-image

Downloads

531

Readme

postcss-svg-mask-image

A PostCSS plugin that rewrites mask-image: svg(...) calls in your CSS into a complete, cross-browser mask setup (mask image, repeat, size, and optional color via background-color). It injects :root CSS variables for each SVG icon into the same file, so the SVG data is stored once and reused everywhere.

One icon can be used in any color and at any size (via color/background and width/height or mask-size).

Best used with icons that are a single compound shape (solid silhouette). Multi-shape or multi-color SVGs can produce unexpected masking results.

Description

This plugin processes CSS and SCSS files to transform mask-image: svg() function calls into standard CSS mask properties. It automatically:

  • Converts SVG files to data URIs
  • Injects CSS variables in :root for each icon (prepended or appended to the file)
  • Replaces svg() calls with the appropriate CSS properties

Installation

npm install postcss postcss-svg-mask-image --save-dev

Basic Setup

Add the plugin to your PostCSS config (e.g. postcss.config.js or postcss.config.cjs):

const path = require("node:path");

module.exports = {
  plugins: [
    require("postcss-svg-mask-image")({
      iconsDir: path.resolve(__dirname, "assets/icons"),
      // maskPositionValue: "center",
      // overwriteRootVars: true,
    }),
  ],
};

Subfolders are supported: svg("arrows/arrow-right") resolves to assets/icons/arrows/arrow-right.svg.

Configuration Options

  • iconsDir (string): Directory where SVG files are stored. Default: path.resolve(process.cwd(), "icons")
  • extension (string): SVG file extension. Default: ".svg"
  • functionName (string): Name of the custom function in CSS (full mask + background injection). Default: "svg"
  • functionNameVar (string | null): Var-only function: replaces with var(--icon-*) only, works on any property. Use this to mix full mask and var-only in one file. Set to null to disable. Default: "svg-var"
  • rootSelector (string): Selector for the rule that holds icon variables. Default: ":root"
  • insertRootAt ("top" | "bottom"): Where to inject the :root rule. Default: "top"
  • overwriteRootVars (boolean): Overwrite existing custom properties in :root. Default: false
  • iconVarPrefix (string): Prefix for generated CSS variables. Default: "--icon-"
  • toVarKey (function): Maps icon name to variable suffix. Default: replaces / and \ with -
  • defaultColor (string): Injected background-color when no second argument to svg(). Default: "currentColor"
  • maskRepeatValue, maskSizeValue (string): Injected mask properties. Defaults: "no-repeat", "100% 100%"
  • maskPositionValue (string | null): Injected mask-position; null disables. Default: null
  • varOnly (boolean): If true, treat svg() as var-only (same behavior as svg-var()). Use when you want var-only everywhere without changing CSS. Default: false
  • properties (string[]): Declaration names to process for svg() (full injection). Default: ["mask-image", "mask"]
  • doNotOverrideBackgroundColor (boolean): Skip injecting background-color if the rule already has one. Default: true

CSS Usage

Best practice: use currentColor

The main intended workflow is to theme icons via color and let the plugin use background-color: currentColor for the mask fill.

.icon {
  width: 1em;
  height: 1em;
  mask-image: svg("arrow-right");
}

.icon.is-muted {
  color: var(--text-muted);
}

.icon.is-danger {
  color: var(--danger);
}

svg() function

In your CSS or SCSS files, use the svg() function. The optional second argument sets background-color (useful as an escape hatch; for most cases prefer currentColor as shown above).

.a {
  width: 1em;
  height: 1em;
  mask-image: svg("arrow-right");
}

.b {
  mask-image: svg("arrow-right", "red");
}

.c {
  mask-image: svg("arrow-right", "var(--color-primary)");
}

The plugin will transform this to:

:root {
  --icon-arrow-right: url("data:image/svg+xml,...");
}

.a {
  width: 1em;
  height: 1em;
  background-color: currentColor;
  mask-image: var(--icon-arrow-right);
  mask-repeat: no-repeat;
  mask-size: 100% 100%;
}

.b {
  background-color: red;
  mask-image: var(--icon-arrow-right);
  mask-repeat: no-repeat;
  mask-size: 100% 100%;
}

.c {
  background-color: var(--color-primary);
  mask-image: var(--icon-arrow-right);
  mask-repeat: no-repeat;
  mask-size: 100% 100%;
}

The :root declarations are injected into the same CSS file (at the top or bottom, see insertRootAt).

svg-var() — var-only (mix with svg())

Use svg-var() when you want only the CSS variable replacement, no mask or background injection. It works on any property (e.g. background-image). You can mix svg() and svg-var() in the same file:

.mask-icon {
  mask-image: svg("arrow");
}
.bg-icon {
  background-image: svg-var("arrow");
}

Becomes:

:root {
  --icon-arrow: url("data:image/svg+xml,...");
}

.mask-icon {
  background-color: currentColor;
  mask-image: var(--icon-arrow);
  mask-repeat: no-repeat;
  mask-size: 100% 100%;
}

.bg-icon {
  background-image: var(--icon-arrow);
}

Set functionNameVar: null to disable svg-var().

varOnly option

With varOnly: true, every svg() call is treated as var-only (same as svg-var()). Use when you want var-only everywhere without changing your CSS to svg-var().

Notes:

  • To pass a CSS variable as the optional color argument, keep it quoted: svg("arrow-right", "var(--color-primary)").
  • If you need per-usage colors, you can also skip the second argument and set color (recommended) or background-color in regular CSS.

SVG cleaning

Before encoding, the plugin strips from each SVG: XML declaration, comments, <metadata>, <title>, <desc>, editor namespaces (e.g. Inkscape/Sodipodi), id, and data-* attributes, so only rendering-relevant markup remains.

For full optimization (e.g. minifying paths, removing default attributes), run your SVGs through SVGO before or alongside this plugin; SVGO is the standard Node.js SVG optimizer.

Requirements

  • PostCSS 8.0+
  • Node.js 22+

License

MIT