Skip to content

poupe-ui/eslint-plugin-tailwindcss

Repository files navigation

@poupe/eslint-plugin-tailwindcss

ESLint plugin for Tailwind CSS v4 with advanced linting rules.

Features

  • 🎯 Tailwind CSS v4 Support - Full support for the latest Tailwind syntax
  • πŸ” Smart Validation - Validates directives, modifiers, and utility classes
  • πŸš€ Auto-fixable Rules - Many rules can automatically fix issues
  • πŸ“¦ Preset Configurations - Ready-to-use configs for different strictness levels
  • 🎨 Theme-aware - Encourages consistent use of design tokens
  • ⚑ Performance - Optimized for large codebases

Requirements

  • ESLint 9.0 or higher
  • Node.js 18.0 or higher
  • Flat config format (eslint.config.js)

Installation

# pnpm
pnpm add -D @poupe/eslint-plugin-tailwindcss @eslint/css

# npm
npm install -D @poupe/eslint-plugin-tailwindcss @eslint/css

# yarn
yarn add -D @poupe/eslint-plugin-tailwindcss @eslint/css

Note: This plugin requires @eslint/css as a peer dependency for CSS parsing.

Usage

Basic Setup

Create an eslint.config.mjs file with TypeScript type checking:

// @ts-check
import tailwindcss from '@poupe/eslint-plugin-tailwindcss';

export default [
  {
    files: ['**/*.css'],
    language: 'css/css', // Required
    plugins: {
      tailwindcss,
    },
    rules: {
      'tailwindcss/valid-theme-function': 'error',
      'tailwindcss/valid-modifier-syntax': 'error',
      'tailwindcss/valid-apply-directive': 'error',
      'tailwindcss/no-arbitrary-value-overuse': 'warn',
      'tailwindcss/prefer-theme-tokens': 'warn',
      'tailwindcss/no-conflicting-utilities': 'error',
    },
  },
];

Using Preset Configurations

Use preset configurations for a quick start:

// @ts-check
import tailwindcss from '@poupe/eslint-plugin-tailwindcss';

export default [
  {
    files: ['**/*.css'],
    language: 'css/css',
    plugins: {
      tailwindcss,
    },
    rules: {
      // Use recommended settings
      ...tailwindcss.configs.recommended.rules,

      // Override specific rules if needed
      'tailwindcss/no-arbitrary-value-overuse': 'error',
    },
  },
];

Available Configurations

minimal

Basic syntax validation only. Good for existing projects.

  • βœ… valid-theme-function
  • βœ… valid-modifier-syntax
  • βœ… valid-apply-directive
  • βœ… no-invalid-at-rules
  • βœ… no-invalid-properties
  • βœ… no-duplicate-imports
  • βœ… no-empty-blocks
  • βœ… no-important

recommended (Default)

Balanced set of rules for most projects.

  • βœ… All rules from minimal
  • βœ… no-conflicting-utilities
  • ⚠️ no-arbitrary-value-overuse (warning)
  • ⚠️ prefer-theme-tokens (warning)

strict

All rules enabled with strict settings. Best for new projects.

  • βœ… All rules as errors
  • βœ… Strictest configuration options
  • βœ… Includes optional @eslint/css rules (logical properties, relative units, layers)

Complete Example

Here's a comprehensive eslint.config.mjs with TypeScript support:

// @ts-check
import js from '@eslint/js';
import typescript from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import css from '@eslint/css';
import tailwindcss from '@poupe/eslint-plugin-tailwindcss';

export default [
  // JavaScript/TypeScript files
  {
    files: ['**/*.{js,mjs,cjs,ts,tsx}'],
    languageOptions: {
      parser: tsParser,
      parserOptions: {
        ecmaVersion: 'latest',
        sourceType: 'module',
      },
    },
    plugins: {
      '@typescript-eslint': typescript,
    },
    rules: {
      ...js.configs.recommended.rules,
      ...typescript.configs.recommended.rules,
    },
  },

  // CSS files with Tailwind CSS support
  {
    files: ['**/*.css'],
    language: 'css/css',
    plugins: {
      css,
      tailwindcss,
    },
    rules: {
      // @eslint/css rules
      'css/no-duplicate-imports': 'error',
      'css/no-empty-blocks': 'error',

      // Tailwind CSS specific rules
      ...tailwindcss.configs.recommended.rules,
    },
  },
];

Rules

Possible Errors (Implemented)

Rules that catch potential bugs or invalid syntax.

Rule Description πŸ”§
no-conflicting-utilities Detects conflicting Tailwind utilities that affect the same CSS properties
no-duplicate-imports Disallow duplicate @import rules
no-empty-blocks Disallow empty rule blocks and at-rule blocks
no-invalid-at-rules Disallow invalid at-rule names and syntax
no-invalid-named-grid-areas Disallow invalid named grid areas in CSS Grid templates
no-invalid-properties Disallow invalid CSS property names
use-baseline Enforce use of widely-supported CSS features
valid-apply-directive Validates the @apply directive usage
valid-modifier-syntax Ensures Tailwind modifiers follow correct syntax patterns
valid-theme-function Validates usage of the theme() function in CSS files πŸ”§

Best Practices (Implemented)

Rules that guide towards better code patterns and maintainability.

Rule Description πŸ”§
no-arbitrary-value-overuse Warns when too many arbitrary values are used instead of theme tokens
no-important Discourage use of !important
prefer-logical-properties Enforce the use of logical properties over physical properties πŸ”§
prefer-theme-tokens Suggests using theme tokens instead of hard-coded values
relative-font-units Prefer relative units (rem/em) over absolute (px) for fonts
use-layers Encourage use of @layer for better CSS architecture

Stylistic Issues (Implemented)

Rules that enforce code style and formatting conventions.

Rule Description πŸ”§
consistent-spacing Enforces consistent spacing around colons in CSS declarations πŸ”§

πŸ”§ = Automatically fixable

Unimplemented Rules (Roadmap)

Possible Errors (Planned)

Core CSS Validation (Additional)

Rules that catch general CSS syntax errors and invalid constructs.

Rule Description πŸ”§ Status
no-unknown-pseudo-class Detect invalid pseudo-classes Planned
no-unknown-pseudo-element Detect invalid pseudo-elements Planned

Best Practices (Planned)

CSS Best Practices (@eslint/css parity)

Rules that enforce modern CSS patterns.

Rule Description πŸ”§ Status
Tailwind v4 Compatibility

Rules specific to Tailwind CSS version management and migration.

Rule Description πŸ”§ Status
version-compatibility Enforce compatibility with specific Tailwind CSS versions Planned
deprecated-features Warn about deprecated Tailwind features Planned
migrate-imports Convert Tailwind v3 imports to v4 syntax πŸ”§ Priority
migrate-directives Update deprecated Tailwind directives πŸ”§ Priority
migrate-config-to-css Guide migration from JS config to CSS @theme Planned
migrate-arbitrary-values Update arbitrary value syntax between versions πŸ”§ Planned
Code Quality

Rules that enforce documentation and maintainability.

Rule Description πŸ”§ Status
comment-word-disallowed-list Disallow specified words in comments Considering
require-description-comments Require explanatory comments for complex selectors Considering
tailwind-comment-directives Validate Tailwind-specific comment directives πŸ”§ Considering

Stylistic Issues (Planned)

CSS Formatting (@eslint/css parity)

General CSS formatting rules.

Rule Description πŸ”§ Status
indent Enforce consistent indentation πŸ”§ Planned
brace-style Enforce consistent brace placement πŸ”§ Planned
block-spacing Enforce consistent spacing inside blocks πŸ”§ Planned
declaration-block-newline Enforce line breaks within declaration blocks πŸ”§ Planned
rule-empty-line-before Require or disallow empty lines before rules πŸ”§ Planned
property-sort-order Enforce consistent property declaration order πŸ”§ Planned
at-rule-formatting Format at-rules consistently πŸ”§ Planned
no-unnecessary-whitespace Disallow unnecessary whitespace πŸ”§ Planned
property-formatting Format property declarations consistently πŸ”§ Planned
selector-formatting Format selectors consistently πŸ”§ Planned
value-formatting Format property values consistently πŸ”§ Planned
media-query-formatting Format media queries consistently πŸ”§ Planned
Tailwind-Specific Formatting

Rules for Tailwind CSS v4 specific constructs.

Rule Description πŸ”§ Status
at-apply-formatting Format @apply directives consistently πŸ”§ Planned
theme-formatting Format @theme blocks consistently πŸ”§ Planned
enforce-class-order Enforce consistent Tailwind utility class ordering πŸ”§ Priority
Comment Formatting

Rules for consistent comment styles.

Rule Description πŸ”§ Status
comment-formatting Format comments consistently πŸ”§ Considering
comment-style Enforce consistent comment syntax πŸ”§ Considering
comment-empty-line-before Require or disallow empty lines before comments πŸ”§ Considering
comment-capitalization Enforce consistent comment capitalization πŸ”§ Considering
comment-length Enforce maximum comment line length πŸ”§ Considering

Status Legend:

  • Priority: High priority, will be implemented next
  • Planned: Scheduled for implementation
  • Considering: Under consideration, may be implemented

Advanced Features

Custom Syntax Support

This plugin extends @eslint/css with Tailwind CSS v4 syntax support:

  • βœ… Directives: @theme, @import, @plugin, @utility, @variant, @source
  • βœ… Functions: theme(), screen()
  • βœ… Arbitrary Values: [value] syntax
  • βœ… Modifiers: hover:, focus:, sm:, lg:, inert:, target:, open:, starting:, popover-open:, not-*:, in-*:, [&:state]:
  • βœ… Stacked Variants: dark:hover:text-white
  • βœ… Custom Variants: Created with @custom-variant

TypeScript Support

Full TypeScript support with exported types:

import type { TailwindCSSRules, TailwindCSSConfigs } from '@poupe/eslint-plugin-tailwindcss';

Configuration Examples

With TypeScript

// eslint.config.mjs
import tailwindcss from '@poupe/eslint-plugin-tailwindcss';
import typescript from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';

export default [
  // TypeScript configuration
  {
    files: ['**/*.{ts,tsx}'],
    languageOptions: {
      parser: tsParser,
      parserOptions: {
        project: './tsconfig.json',
        tsconfigRootDir: import.meta.dirname,
      },
    },
    plugins: {
      '@typescript-eslint': typescript,
    },
    rules: {
      ...typescript.configs['recommended-type-checked'].rules,
    },
  },
  // Tailwind CSS configuration
  {
    files: ['**/*.css'],
    ...tailwindcss.configs.recommended,
  },
];

Vue.js Project

// eslint.config.mjs
import tailwindcss from '@poupe/eslint-plugin-tailwindcss';
import vue from 'eslint-plugin-vue';

export default [
  ...vue.configs['flat/recommended'],
  {
    files: ['**/*.{css,vue}'],
    ...tailwindcss.configs.recommended,
  },
];

With PostCSS

// @ts-check
// eslint.config.mjs
import tailwindcss from '@poupe/eslint-plugin-tailwindcss';

export default [
  {
    files: ['**/*.{css,pcss,postcss}'],
    ...tailwindcss.configs.strict,
  },
];

Troubleshooting

ESLint can't find the plugin

Make sure you're using ESLint flat config format (ESLint 9+):

// @ts-check
// βœ… Correct - eslint.config.mjs (ESM format)
export default [
  tailwindcss.configs.recommended,
];

// ❌ Wrong - .eslintrc.js (legacy format)
module.exports = {
  extends: ['@poupe/eslint-plugin-tailwindcss'],
};

Rules not applying to CSS files

Ensure your config targets CSS files:

export default [
  {
    files: ['**/*.css'], // Don't forget this!
    ...tailwindcss.configs.recommended,
  },
];

Contributing

Contributions are welcome! Please read our contributing guidelines first.

Development

# Install dependencies
pnpm install

# Run tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Run tests with coverage
pnpm test:coverage

# Build
pnpm build

# Lint and auto-fix
pnpm lint

# Type checking
pnpm type-check

# Run all pre-commit checks
pnpm precommit

Testing

Tests are written using Vitest and ESLint's RuleTester. Each rule should have comprehensive test coverage including:

  • Valid code examples
  • Invalid code examples with expected errors
  • Auto-fix scenarios (where applicable)
  • Edge cases and CSS parsing quirks

Example test structure:

import { RuleTester } from 'eslint';
import css from '@eslint/css';
import { ruleName } from '../../rules/rule-name';

const ruleTester = new RuleTester({
  language: 'css/css',
  plugins: { css },
});

describe('rule-name', () => {
  ruleTester.run('tailwindcss/rule-name', ruleName, {
    valid: [
      // Valid test cases
    ],
    invalid: [
      // Invalid test cases with expected errors
    ],
  });
});

License

MIT Β© Apptly Software Ltd

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •