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

unplugin-css-checker

v1.0.0

Published

Check CSS pollution for bundlers

Readme

English | 简体中文

CSS Pollution Checker Plugin

Installation

npm i -D unplugin-css-checker

Vite

// vite.config.ts
import CSSChecker from 'unplugin-css-checker/vite'

export default defineConfig({
  plugins: [
    CSSChecker({ /* options */ }),
  ],
})

Rollup

// rollup.config.js
import CSSChecker from 'unplugin-css-checker/rollup'

export default {
  plugins: [
    CSSChecker({ /* options */ }),
  ],
}

Webpack

// webpack.config.js
module.exports = {
  /* ... */
  plugins: [
    require('unplugin-css-checker/webpack')({ /* options */ })
  ]
}

Vue-cli

// vue.config.js
module.exports = {
  configureWebpack: {
    plugins: [
      require('unplugin-css-checker/webpack')({ /* options */ }),
    ],
  },
}

esbuild

// esbuild.config.js
import { build } from 'esbuild'
import CSSChecker from 'unplugin-css-checker/esbuild'

build({
  plugins: [CSSChecker()],
})

Usage Examples

import { defineConfig, loadEnv } from 'vite'
import { createVuePlugin } from 'vite-plugin-vue2'

export default defineConfig(({ mode, command }) => {
  const env = loadEnv(mode, process.cwd())
  const isDev = command === 'serve'

  return {
    plugins: [
      createVuePlugin(),
      cssChecker({
        // Declare when to enable plugin checking. Since this plugin will terminate the build if the check fails,
        // it's not recommended to set it to true directly to avoid affecting the build output
        // To avoid affecting the build output, this configuration defaults to false
        enable: isDev || !!env.VITE_CHECK_CSS,

        // Declare the project root directory, required
        projectRoot: __dirname,

        // Declare which file extensions to check, defaults to checking `.css`, `.pcss`, `.postcss`, `.less`, `.scss`, `.sass`
        suffixes: ['.css', '.pcss', '.postcss', '.less', '.scss', '.sass'],

        // Configure public styles, required
        immutables: {
          // Configure which files or directories are public styles
          libs: [
            // Declare sfv component library as public styles
            'node_modules/your-components/dist/themes',
            // Declare the global styles directory, will automatically read all files
            'src/style',
          ],

          // Manually specify public style class names
          selectors: ['el-lang'],

          // Declare which class names in public style files are not public styles
          excludeSelectors: [
            '.iconfont',
            /\[ant\]/,
          ],
        },

        // Declare which files to exclude from checking, if public styles are not globally injected, this needs to be configured
        excludeRules: [
          /windi\.css$/,
          /src[\\\/]style/,
        ],
      }),
    ],
  }
})

How It Works

Definition of a "rule": .sfv-btn { color: red; } is one rule, .sfv-btn, .custom-btn { color: red; } is two rules

  1. When the build tool performs buildStart, collect all public style class names.
  2. When the build tool performs transform, start checking each file.
  3. If enable is not true or the file extension is not supported, and it's not a style code block in a vue file, then end.
  4. Check if it's a scoped style in a vue file, if yes then end.
  5. Parse the CSS code and extract rules.
  6. Check if all class selectors in each rule are public style class names, if yes then mark as style pollution.

Why These Types of Pollution Are Not Checked

Scoped Styles

  1. Scoped adds attribute selectors, even when using /deep/ for penetration, it will still have them. Even if it pollutes, it can only pollute things inside slots.
  2. If we want to check slots, the cost would be high and cannot be achieved through static analysis. It would require using a headless browser for e2e testing, which contradicts this plugin's positioning (a static analysis plugin).

Why Not Check for Same Class Names Used in Multiple Files

  1. Vite is bundless, unless building, it cannot know all file information and cannot know during dev that other files are using the same class names.
  2. If we pre-scan all files to get all class names, it would be difficult to handle in large project scenarios, whether for storage, matching, or other processes, it would be a huge overhead. Considering the cost-benefit ratio, we don't plan to support this for now.
  3. If there are scenarios where the same class names are used across projects, this can be handled through custom public style class names.

Why Not Check ID, Pseudo-classes, Pseudo-elements, and Tag Selectors

ID Selectors

Normally, we shouldn't set styles for ID selectors, and even if we do, it should be set where it's used.

In HTML, element IDs need to be unique, so theoretically there shouldn't be cases where unrelated files pollute ID selector styles.

We can consider adding corresponding checks when needed in the future.

Tag Selectors

Generally, tag selectors don't work alone, they only work alone in reset scenarios.

This means that in business scenarios, we normally don't directly override tag styles, but instead use classes or atomic CSS or other methods to override, so there's no corresponding check.

We can consider adding corresponding checks when needed in the future.

Pseudo-classes and Pseudo-elements

These two types of selectors basically need to work together with other selectors, like class selectors, so there's no corresponding check.

We can consider adding corresponding checks when needed in the future.