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

dynamic-css-plugin

v2.2.1

Published

Vite / Webpack - plugin to transform dynamic css class names on-the-fly

Readme

Dynamic CSS Plugin

Patch. Inject. Transform.

"btn-primary btn-primary-disabled" ==> .app_Xscyf.app_LfRuA

Supported frameworks:

Advantages:

  • 👌 Prevent conflicts with third party CSS
  • ❤️‍🔥 Smaller bundle size
  • 💥 Obfuscate class names

How it works:

  1. Patch into the framework's DOM rendering setAttribute method to intercept class names as they are applied to elements
  2. Inject a custom setAttribute method into the bundle that runs the transformation logic
  3. Transform class names at run-time and cooresponding CSS at build-time

Getting Started

Install

npm install dynamic-css-plugin -D

Vite

vite.config.js

Import into Vite config

import dynamicCssPlugin from "dynamic-css-plugin/vite";

Add to Vite plugins

plugins: [
	dynamicCssPlugin({
		transform: "app_[md4:hash:base64:5]"
	})
];

Full Vite example


Webpack

webpack.config.js

Import into Webpack config

import DynamicCssPlugin from "dynamic-css-plugin/webpack";

Add to Webpack plugins

plugins: [
	new DynamicCssPlugin({
		transform: "app_[md4:hash:base64:5]"
	})
];

Full Webpack example

Options

  • enabled: true - If false, the plugin will not run

  • scope: "" - Applies a scope to the injected method. Useful if multiple instances are on the same page such as with micro-frontends

  • debug: false - Enables debug logging

Transform

  • transform: "[md4:hash:base64:5]" - The transform template or config object

  • transform: {} - The transform config object

    • transform.template: "[md4:hash:base64:5]" - The format of transformed class names

      • "prefix_[{algorithm}:hash:{encoding}:{length}]"
    • transform.attributes: /^(class)$/ - Regex for HTML attributes to transform

    • transform.ignoreTags: /(path)/i - Regex for HTML tags to ignore

    • transform.ignoreValues: /^(css|sc|icon)-/i - Regex for HTML attribute values to ignore

    • transform.ignoreFiles: /\.notransform\.(css|scss)$/i - Regex for files to ignore

Inject

  • inject: {} - The injection config

    • inject.entryPoint: undefined The entry point for the injected method in the bundle, if undefined the first entry is used

    • inject.src: "./src/inject/index.js" The code to apply options and generate the file to inject

    • inject.file: "./src/inject/index_generated.js" The code to inject

Patch

  • patch: PatchReactDom - The patch function

    import PatchReactDom from "dynamic-css-plugin/patch/react-dom";

    Patch method signature:

    function PatchReactDom(scope = "") {
    	return {
    		test: /react-dom/,
    		search: /(\w+)\.setAttribute\(/g,
    		replace: `globalThis['${scope}setAttributeDynamic'].call($1,`
    	};
    }

Notes

ignoreValues default excludes class names with the following prefixes that are commonly generated by other libraries and should not be transformed

  • css- which is the emotion default
  • sc- which is the styled-components default
  • icon- which is the the standard for icon classes

Limitations

Since we are only patching calls to "setAttribute" inside react-dom that means if a class is applied a different way such as with vanilla JS or using classList the transform will not apply. This is largely ok since these patterns don’t necessarily follow the "react way of doing things". However if you do need to support these patterns you can use the injected method directly.

For example:

import DynamicCss from "dynamic-css-plugin";

document.body.classList.add(DynamicCss("theme-light"));

To avoid issues, the plugin supports options to ignore specific tags and values. Additionally the plugin does not transform ids, this is done purposely so that tests and analytics can still reliably target elements.