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 🙏

© 2025 – Pkg Stats / Ryan Hefner

eslint-plugin-undefined-css-classes

v0.1.5

Published

ESLint plugin to detect undefined CSS classes in HTML/JSX

Downloads

135

Readme

eslint-plugin-undefined-css-classes

An ESLint plugin to detect undefined CSS classes in your HTML and JSX code. Automatically ignores Tailwind CSS classes when Tailwind is detected in your project.

📚 Documentation

✨ Features

  • Detects CSS classes used in HTML/JSX/Svelte that are not defined in any CSS file
  • Automatically detects and ignores Tailwind CSS classes (both static and dynamic)
  • Full Tailwind CSS 4 support - detects @import "tailwindcss" and @theme directives
  • Supports JSX className and class attributes
  • Supports Svelte components (requires eslint-plugin-svelte)
  • Supports template literals and dynamic class names
  • Works with CSS-in-JS solutions like clsx, classNames, and cn
  • Configurable patterns for ignoring specific classes
  • Caches CSS parsing for better performance

📦 Installation

npm install --save-dev eslint-plugin-undefined-css-classes

or

yarn add -D eslint-plugin-undefined-css-classes

🚀 Quick Start

Add the plugin to your ESLint configuration:

.eslintrc.json

{
  "plugins": ["undefined-css-classes"],
  "rules": {
    "undefined-css-classes/no-undefined-css-classes": "error"
  }
}

Using predefined configs

The plugin provides several predefined configurations:

Recommended (default)

{
  "extends": ["plugin:undefined-css-classes/recommended"]
}

With Tailwind

{
  "extends": ["plugin:undefined-css-classes/with-tailwind"]
}

Strict (no Tailwind, no dynamic classes)

{
  "extends": ["plugin:undefined-css-classes/strict"]
}

⚙️ Configuration Options

"undefined-css-classes/no-undefined-css-classes": ["error", {
  // Glob patterns for CSS files to scan
  "cssFiles": ["**/*.css"],
  
  // Patterns to exclude from scanning
  "excludePatterns": ["**/node_modules/**"],
  
  // Ignore Tailwind CSS classes (default: true)
  "ignoreTailwind": true,
  
  // Only ignore Tailwind if config file exists (default: true)
  "requireTailwindConfig": true,
  
  // Regex patterns for classes to ignore
  "ignoreClassPatterns": ["^custom-", "^legacy-"],
  
  // Allow dynamic classes with template literals (default: true)
  "allowDynamicClasses": true,
  
  // Base directory for CSS file resolution
  "baseDir": null
}]

📝 Examples

Valid Code

// Defined in CSS
<div className="defined-class">Content</div>

// Tailwind classes (when ignoreTailwind: true)
<div className="flex items-center bg-blue-500">Content</div>

// Dynamic Tailwind classes
<div className="w-[100px] h-[200px]">Content</div>

// Template literals with defined classes
<div className={`defined-class ${condition ? "another-defined" : "btn-primary"}`}>Content</div>

// Dynamic classes (when allowDynamicClasses: true)
<div className={`prefix-${variant}`}>Content</div>

Invalid Code

// Undefined class
<div className="undefined-class">Content</div>
// Error: CSS class 'undefined-class' is not defined in any CSS file

// Multiple undefined classes
<div className="undefined-one undefined-two">Content</div>
// Error: CSS classes undefined-one, undefined-two are not defined in any CSS file

// Undefined class in classList.add
element.classList.add("undefined-class");
// Error: CSS class 'undefined-class' is not defined in any CSS file

🎨 Tailwind CSS Detection

Implementation Approach

The plugin uses a hybrid approach for detecting Tailwind CSS classes:

  1. Pattern-based detection: Uses comprehensive regex patterns to match Tailwind utilities
  2. Definition-based detection: Uses a structured class definition system similar to tailwind-merge for accurate validation

🎨 Tailwind CSS Support

The plugin automatically detects Tailwind CSS in your project through multiple methods:

Tailwind CSS 3 and earlier

  • Presence of tailwind.config.js, tailwind.config.ts, or other config files
  • tailwindcss in package.json dependencies
  • tailwindcss in PostCSS configuration

Tailwind CSS 4

  • @import "tailwindcss" in CSS files
  • @theme directive in CSS files
  • @import "tailwindcss/theme" or @import "tailwindcss/utilities"

Custom Theme Colors

The plugin intelligently ignores custom utility classes that would be generated from @theme definitions:

  • text-primary, bg-surface, border-inverse etc.
  • Custom color scales like text-brand-500, bg-surface-tertiary

🧩 Svelte Support

To use this plugin with Svelte components, you need to install and configure eslint-plugin-svelte:

Installation

npm install --save-dev eslint-plugin-svelte svelte-eslint-parser

Configuration

// eslint.config.js
import svelte from 'eslint-plugin-svelte';
import undefinedCssClasses from 'eslint-plugin-undefined-css-classes';

export default [
  ...svelte.configs['flat/recommended'],
  {
    files: ['**/*.svelte'],
    plugins: {
      'undefined-css-classes': undefinedCssClasses
    },
    rules: {
      'undefined-css-classes/no-undefined-css-classes': ['error', {
        cssFiles: ['src/**/*.css'],
        ignoreTailwind: true
      }]
    }
  }
];

Example Svelte Component

<script>
  export let title = 'Hello';
</script>

<!-- Valid: defined classes -->
<div class="container defined-class">
  <h1 class="font-display">{title}</h1>
</div>

<!-- Invalid: undefined classes -->
<div class="fake-undefined-class">
  <!-- Error: CSS class 'fake-undefined-class' is not defined -->
</div>

🎨 Tailwind CSS Support

Automatic Detection

The plugin automatically detects if your project uses Tailwind CSS by checking for:

  1. Tailwind configuration files (tailwind.config.js, tailwind.config.ts, etc.)
  2. tailwindcss in package.json dependencies
  3. Tailwind references in postcss.config.js

When Tailwind is detected and ignoreTailwind is true, the plugin will ignore:

  • Tailwind utility classes (flex, grid, text-blue-500, etc.)
  • Responsive modifiers (sm:, md:, lg:, etc.)
  • State modifiers (hover:, focus:, active:, etc.)
  • Arbitrary value classes ([100px], [#ff0000], etc.)
  • Dynamic classes with template literals

⚡ Performance

  • CSS files are parsed once and cached
  • Tailwind detection is cached per session
  • Use specific cssFiles patterns to limit scanning scope
  • Consider using excludePatterns to skip unnecessary directories

🔧 Compatibility

  • ESLint: >=7.0.0
  • Node.js: >=18.18.0
  • Supports JSX/TSX files (React, Next.js, etc.)
  • Supports Svelte components (with eslint-plugin-svelte)
  • Vue support requires vue-eslint-parser (see docs)

Test Coverage

  • 223 tests across 13 test suites
  • Comprehensive coverage including:
    • Tailwind CSS v3 & v4 patterns
    • Dynamic class generation
    • CSS-in-JS utilities (clsx, classNames, cn)
    • Unicode and emoji support in class names
    • Malformed CSS handling
    • Long class names (1000+ characters)
    • Nested conditionals and expressions

🐛 Debug Mode

To enable debug output for troubleshooting, set the DEBUG environment variable:

DEBUG=1 npx eslint src/

This will output additional information about:

  • CSS file parsing
  • Tailwind detection
  • Class extraction
  • Cache operations

Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

npm test  # Run all 223 tests
npm run lint  # Check code style

📄 License

MIT