or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-postcss-selector-not

PostCSS plugin to transform :not() W3C CSS level 4 pseudo class to :not() CSS level 3 selectors

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/postcss-selector-not@8.0.x

To install, run

npx @tessl/cli install tessl/npm-postcss-selector-not@8.0.0

index.mddocs/

PostCSS Selector Not

PostCSS Selector Not is a PostCSS plugin that transforms CSS level 4 :not() pseudo-class selectors with multiple arguments into CSS level 3 compatible selectors. It converts modern :not(.a, .b) syntax to :not(.a):not(.b) to ensure compatibility with older browsers while allowing developers to use the more concise modern syntax.

Package Information

  • Package Name: postcss-selector-not
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install postcss-selector-not --save-dev
  • Node Version: >=18
  • PostCSS Version: ^8.4 (peer dependency)

Core Imports

import postcssSelectorNot from "postcss-selector-not";
// Named export also available
import type { pluginOptions } from "postcss-selector-not";

For CommonJS:

const postcssSelectorNot = require("postcss-selector-not");

Basic Usage

import postcss from "postcss";
import postcssSelectorNot from "postcss-selector-not";

// Basic PostCSS usage
const result = await postcss([
  postcssSelectorNot()
]).process(css, { from: undefined });

console.log(result.css);

Example transformation:

/* Input CSS */
p:not(:first-child, .special) {
  color: red;
}

/* Output CSS */
p:not(:first-child):not(.special) {
  color: red;
}

Architecture

PostCSS Selector Not follows the standard PostCSS plugin architecture:

  • Plugin Creator: Factory function that returns a PostCSS plugin instance
  • Rule Processing: Processes CSS rules containing :not() selectors
  • Selector Parsing: Uses postcss-selector-parser for reliable CSS selector manipulation
  • Error Handling: Provides warnings for invalid selectors without breaking the build
  • Transformation Logic: Expands multi-argument :not() selectors into separate single-argument :not() functions

Capabilities

Plugin Creator Function

Creates a PostCSS plugin instance for transforming :not() selectors.

/**
 * Creates a PostCSS plugin for transforming CSS level 4 :not() selectors
 * @param options - Plugin configuration options (currently none supported)
 * @returns PostCSS plugin instance
 */
declare function postcssSelectorNot(options?: pluginOptions): Plugin;

/** Plugin options type - currently no options are supported */
type pluginOptions = Record<string, never>;

The plugin creator function returns a PostCSS plugin object with:

  • postcssPlugin: String identifier "postcss-selector-not"
  • Rule: Function that processes CSS rules containing :not() selectors

Plugin Properties

/** PostCSS plugin flag indicating this is a valid PostCSS plugin */
postcssSelectorNot.postcss: true;

Transformation Behavior

The plugin specifically targets :not() pseudo-class selectors that contain multiple simple selectors separated by commas. It performs the following transformations:

  • Input: :not(.a, .b)Output: :not(.a):not(.b)
  • Input: :not(tag1, tag2, tag3)Output: :not(tag1):not(tag2):not(tag3)
  • Input: :not(:hover, :focus)Output: :not(:hover):not(:focus)

Supported selectors:

  • Class selectors: .class
  • Type selectors: tag
  • ID selectors: #id
  • Pseudo-class selectors: :hover, :focus, etc.
  • Attribute selectors: [attr="value"]

Limitations:

  • Only simple selectors are supported within :not()
  • Complex selectors like :not(.a > .b, .c ~ .d) cannot be downgraded and will be left unchanged
  • The plugin only processes selectors that contain :not( (case-insensitive)

Error Handling

The plugin includes comprehensive error handling:

  • Selector Parsing Errors: If a selector cannot be parsed by postcss-selector-parser, the plugin will issue a PostCSS warning with the selector string and error message
  • Invalid Selectors: Malformed selectors are reported but don't break the build process
  • Graceful Degradation: When transformation fails, the original selector is preserved

Warning Format:

Failed to parse selector : "invalid-selector" with message: "error details"

Types

/** Plugin options type - currently no configuration options are supported */
type pluginOptions = Record<string, never>;

/** PostCSS Plugin interface */
interface PostCSSPlugin {
  postcssPlugin: string;
  Rule(rule: PostCSSRule, helpers: { result: PostCSSResult }): void;
}

/** PostCSS Rule interface (from postcss library) */
interface PostCSSRule {
  selector: string;
  warn(result: PostCSSResult, message: string): void;
  clone(overrides: { selector: string }): PostCSSRule;
  replaceWith(newRule: PostCSSRule): void;
}

/** PostCSS Result interface (from postcss library) */
interface PostCSSResult {
  // PostCSS processing result object
}

Usage Examples

Basic Webpack Configuration

const postcssSelectorNot = require("postcss-selector-not");

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  postcssSelectorNot()
                ]
              }
            }
          }
        ]
      }
    ]
  }
};

PostCSS Configuration File

// postcss.config.js
module.exports = {
  plugins: [
    require("postcss-selector-not")()
  ]
};

Complex Selector Examples

/* Multiple pseudo-classes */
.button:not(:hover, :focus, :active) {
  opacity: 0.8;
}
/* Becomes: */
.button:not(:hover):not(:focus):not(:active) {
  opacity: 0.8;
}

/* Mixed selector types */
article:not(.featured, #special, [data-premium]) {
  margin: 1rem;
}
/* Becomes: */
article:not(.featured):not(#special):not([data-premium]) {
  margin: 1rem;
}

/* Nested :not() selectors */
.container :not(h1, h2) :not(.icon, .badge) {
  font-size: 0.9rem;
}
/* Becomes: */
.container :not(h1):not(h2) :not(.icon):not(.badge) {
  font-size: 0.9rem;
}