css-selector-generator

repository·master·Indexed 20 days ago

https://github.com/fczbkk/css-selector-generator

A JavaScript library for generating optimized and unique CSS selectors for single or multiple DOM elements. It supports Shadow DOM, virtual DOM environments, and provides tools to handle CSS-in-JS generated class names. The library includes functions like getCssSelector for the simplest selector and cssSelectorGenerator for yielding all possible selector combinations, with support for custom root elements, blacklists, whitelists, and priority configuration for selector types.

Tokens
8.6K
Snippets
41
Records
43
Agent score
69%

What's inside css-selector-generator

  1. How the fallback mechanism works

    master

    The library attempts to find the shortest CSS selector for the parent-to-child relationship from the target element up to the root element.

    • If a relationship is not unique, it uses a * wildcard (e.g., #wrapper > * > div > .text).
    • If even the wildcard selector is not unique, it falls back to a chain of :nth-child selectors (e.g., :nth-child(2) > :nth-child(4) > :nth-child(1) > :nth-child(12)).
  2. Generate selectors for Shadow DOM elements

    master

    The library automatically detects if an element is part of a Shadow DOM tree and generates a selector relative to the shadow root. You can also explicitly specify the shadow root using the root option in the configuration object.

    const shadowRoot = element.attachShadow({ mode: "open" });
    const shadowElement = shadowRoot.appendChild(document.createElement("div"));
    shadowElement.className = "shadowElement";
    
    // Automatically detects shadow root
    getCssSelector(shadowElement);
    // ".shadowElement"
    
    // Or explicitly specify the shadow root
    getCssSelector(shadowElement, { root: shadowRoot });
    // ".shadowElement"
  3. Use css-selector-generator without NPM

    master

    If you are not using a package manager, you can download the files from the build folder and include them directly in your HTML via a <script> tag. When used this way, the library is exposed under the CssSelectorGenerator namespace.

    <!-- link the library -->
    <script src="build/index.js"></script>
    <script>
      CssSelectorGenerator.getCssSelector(targetElement);
    </script>
  4. Optimize performance with combination and candidate limits

    master

    For elements with many attributes or classes (common in atomic CSS frameworks), selector generation can become exponentially slow. Use these options to limit the search space:

    • maxCombinations: Limits the number of combinations attempted between class names.
    • maxCandidates: Limits the total number of selector candidates evaluated for each element.
    // Limit combinations to prevent exponential slowdown
    getCssSelector(targetElement, { maxCombinations: 100 });
    
    // Limit total candidates
    getCssSelector(targetElement, { maxCandidates: 100 });
  5. Configure selector types and priority

    master

    You can control which types of CSS selectors the generator uses by providing an array to the selectors option. The order of the array defines the priority: the generator will attempt to use the types earlier in the array first.

    Valid selector types are:

    • id
    • class
    • tag
    • attribute
    • nthchild
    • nthoftype
    // Only use classes
    getCssSelector(targetElement, { selectors: ["class"] });
    
    // Prioritize tags over classes
    getCssSelector(targetElement, { selectors: ["tag", "class"] });
  6. Use the experimental :scope option

    master

    When useScope: true is set and a root is provided, fallback selectors are generated relative to the root using the :scope pseudo-class instead of traversing from :root (the <html> element).

    // Generates selectors relative to the provided root using :scope
    getCssSelector(needleElement, {
      root: haystackElement,
      useScope: true,
    });
  7. Use getCssSelector to find the first available selector

    master

    The getCssSelector function returns the first (typically simplest) CSS selector found for a given DOM element. You can pass an optional configuration object as the second parameter.

    To use it with NPM, import the function from css-selector-generator.

    import { getCssSelector } from "css-selector-generator";
    
    // Returns the first found selector
    const selector = getCssSelector(targetElement);
    
    // Returns a selector with specific options
    const selectorWithOptions = getCssSelector(targetElement, { includeTag: true });
  8. Limit results in cssSelectorGenerator

    master

    The cssSelectorGenerator() function (unlike getCssSelector()) can yield multiple selector options. Because the number of possible combinations grows exponentially ($2^n$ for $n$ classes), you should use maxResults to limit the output and prevent performance issues.

    // Limit to the 5 best/simplest selectors
    const fewSelectors = [
      ...cssSelectorGenerator(needleElement, {
        selectors: ["class"],
        maxResults: 5,
      }),
    ];
  9. Handle CSS-in-JS generated class names

    master

    When working with libraries like Emotion, styled-components, or MUI, class names are often unstable. Set ignoreGeneratedClassNames: true to use heuristics that skip these generated names in favor of human-readable ones (e.g., skipping .css-1x2y3z to use .button-primary).

    Note: The whitelist option takes precedence over this setting. If a generated class is whitelisted, it will be used.

    If the built-in heuristics fail, you can use a custom function in the blacklist to detect generated classes.

    // Enable heuristic filtering
    getCssSelector(targetElement, { ignoreGeneratedClassNames: true });
    
    // Custom blacklist logic for generated classes
    getCssSelector(targetElement, {
      blacklist: [
        (className) => /^css-|sc-|makeStyles-.*/.test(className),
      ],
    });
  10. Define the root element for selector generation

    master

    By default, the generator uses the document root. You can specify a different starting point for the selector path by providing a root element in the options. This is useful for generating relative selectors within a specific container.

    getCssSelector(targetElement, {
      root: document.querySelector(".myRootElement"),
    });
  11. Use TypeScript with css-selector-generator

    master

    The library includes built-in type definitions. You can import types like CssSelectorGeneratorOptionsInput and CssSelectorType directly from css-selector-generator/types/types.js to ensure type safety when configuring the generator.

    import { getCssSelector } from "css-selector-generator";
    import type {
      CssSelectorGeneratorOptionsInput,
      CssSelectorType,
    } from "css-selector-generator/types/types.js";
    
    const options: CssSelectorGeneratorOptionsInput = {
      selectors: ["class", "id", "tag"],
      blacklist: [".ignore-*"],
      root: document.body,
    };
    
    const selector = getCssSelector(targetElement, options);