• Stars
    star
    533
  • Rank 83,238 (Top 2 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created almost 11 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

JavaScript object that creates unique CSS selector for given element.

CSS Selector Generator

JavaScript object that creates a unique CSS selector for a given DOM element or multiple DOM elements.

It also generates shorter selectors and is faster and/or more robust than many other libraries - see this comparison and select the best alternative for your use case.

Install

Add the library to your project via NPM or Yarn.

npm install css-selector-generator
yarn add css-selector-generator

Then include it in your source code:

import { getCssSelector } from "css-selector-generator";

How to use

Simplest way to use it is to provide an element reference, without any options.

<body>
  <!-- targetElement -->
  <div class="myElement"></div>
</body>
getCssSelector(targetElement);
// ".myElement"

Typical example is to create a selector for any element that the user clicks on:

// track every click
document.body.addEventListener("click", function (event) {
  // get reference to the element user clicked on
  const element = event.target;
  // get unique CSS selector for that element
  const selector = getCssSelector(element);
  // do whatever you need to do with that selector
  console.log("selector", selector);
});

Usage without NPM

If you don't want to use this library with NPM, you can download it directly from the "build" folder and insert it to your HTML document directly. In this case, the library is wrapped in namespace CssSelectorGenerator. So the usage would look something like this:

<!-- link the library -->
<script src="build/index.js"></script>
<script>
	CssSelectorGenerator.getCssSelector(targetElement)
</script

Usage with virtual DOM (e.g. JSDOM)

If you want to use this library with Node, usually for testing, don't require it directly into the Node process. It will not work, because there's no window object and there are no elements to select. Instead, you have to add the library to the virtual window object. Here are instructions how to do it in JSDOM, other libraries will work in a similar way: https://github.com/jsdom/jsdom/wiki/Don't-stuff-jsdom-globals-onto-the-Node-global

Multi-element selector

This library also allows you to create selector targeting multiple elements at once. You do that by calling the same function, but you provide an array of elements instead of single element:

<body>
  <!-- firstElement -->
  <div class="aaa bbb"></div>
  <!-- secondElement -->
  <span class="bbb ccc"></span>
</body>
getCssSelector([firstElement, secondElement]);
// ".bbb"

If it is not possible to construct single selector for all elements a standalone selector for each element will be generated:

<body>
  <!-- firstElement -->
  <div></div>
  <!-- secondElement -->
  <span></span>
</body>
getCssSelector([firstElement, secondElement]);
// "div, span"

Fallback

getCssSelector determines the shortest CSS selector for parent -> child relationship, from the input Element until the Root Element.

If there is no unique selector available for any of these relationships (parent -> child), a fallback of * will be used for this relationship.

#wrapper > * > div > .text

In some cases, this selector may not be unique (e.g. #wrapper > * > div > *). In this case, it will fall back to an entire chain of :nth-child selectors like:

":nth-child(2) > :nth-child(4) > :nth-child(1) > :nth-child(12)"

Options

Selector types

You can choose which types of selectors do you want to use:

<body>
  <!-- targetElement -->
  <div class="myElement"></div>
</body>
getCssSelector(targetElement, { selectors: ["class"] });
// ".myElement"
getCssSelector(targetElement, { selectors: ["tag"] });
// "div"

Order of selector types defines their priority:

getCssSelector(targetElement, { selectors: ["class", "tag"] });
// ".myElement"
getCssSelector(targetElement, { selectors: ["tag", "class"] });
// "div"

Valid selector types are:

  • id
  • class
  • tag
  • attribute
  • nthchild
  • nthoftype

Root element

You can define root element, from which the selector will be created. If root element is not defined, document root will be used:

<body>
  <div class="myRootElement">
    <!-- targetElement -->
    <div class="myElement"></div>
  </div>
</body>
getCssSelector(targetElement);
// ".myRootElement > .myElement"
getCssSelector(targetElement, {
  root: document.querySelector(".myRootElement"),
});
// ".myElement"

Blacklist

If you want to ignore some selectors, you can put them on the blacklist. Blacklist is an array that can contain either regular expressions, strings and/or functions.

In strings, you can use an asterisk (*) as a wildcard that will match any number of any characters.

Functions will receive a selector as a parameter. They should always return boolean, true if it is a match, false if it is not. Any other type of return value will be ignored.

<body>
  <!-- targetElement -->
  <div class="firstClass secondClass"></div>
</body>
getCssSelector(targetElement, { blacklist: [".firstClass"] });
// ".secondClass"
getCssSelector(targetElement, { blacklist: [".first*"] });
// ".secondClass"
getCssSelector(targetElement, { blacklist: [/first/] });
// ".secondClass"
getCssSelector(targetElement, {
  blacklist: [(input) => input.startsWith(".second")],
});
// ".secondClass"

You can target selectors of any types using the blacklist.

getCssSelector(targetElement, {
  blacklist: [
    // ID selector
    "#forbiddenId",
    // class selector
    ".forbiddenClass",
    // attribute selector
    "[forbidden-attribute]",
    // tag selector
    "div",
  ],
});

Whitelist

Same as blacklist option, but instead of ignoring matching selectors, they will be prioritised.

<body>
  <!-- targetElement -->
  <div class="firstClass secondClass"></div>
</body>
getCssSelector(targetElement, { whitelist: [".secondClass"] });
// ".secondClass"
getCssSelector(targetElement, { whitelist: [".second*"] });
// ".secondClass"
getCssSelector(targetElement, { whitelist: [/second/] });
// ".secondClass"

Combine within selector

If set to true, the generator will try to look for combinations of selectors within a single type (usually class names) to get better overall selector.

<body>
  <!-- targetElement -->
  <div class="aaa bbb"></div>
  <div class="aaa ccc"></div>
  <div class="bbb ccc"></div>
</body>
getCssSelector(targetElement, { combineWithinSelector: false });
// "body > :nth-child(1)" - in this case no single class name is unique
getCssSelector(targetElement, { combineWithinSelector: true });
// ".aaa.bbb"

This option is set to true by default. It can be set to false for performance reasons.

Combine between selectors

If set to true, the generator will try to look for combinations of selectors between various types (e.g. tag name + class name) to get better overall selector.

<body>
	<!-- targetElement -->
	<div class="aaa"></div>
	<div class="bbb"></div>
	<p class="aaa"></div>
</body>
getCssSelector(targetElement, { combineBetweenSelectors: false });
// "body > :nth-child(1)" - in this case no single class name or tag name is unique
getCssSelector(targetElement, { combineBetweenSelectors: true });
// "div.aaa"

This option is set to true by default. It can be set to false for performance reasons.

Include tag

This option will add tag selector type to every selector:

<body>
  <!-- targetElement -->
  <div class="myElement"></div>
</body>
getCssSelector(targetElement, { includeTag: true });
// "div.myElement"

Max combinations

This is a performance optimization option that can help when trying to find a CSS selector within elements that contain large numbers of class names (e.g. because of frameworks that create atomic styles) or other attributes.

In such case, the number of possible combinations between class names can be too large (it grows exponentially) and can significantly slow down selector generation. In reality, if the selector is not found within first few combinations, it usually won't be found within the rest of combinations.

getCssSelector(targetElement, { maxCombinations: 100 });

Max candidates

Performance optimization option, similar to maxCombinations. This does limit a total number of selector candidates for each element.

You should use it in cases, when there are not too many class names and attributes, but they are numerous enough to produce large number of combinations between them.

getCssSelector(targetElement, { maxCandidates: 100 });

Bug reports, feature requests and contact

If you found any bugs, if you have feature requests or any questions, please, either file an issue on GitHub or send me an e-mail at [email protected]

License

CSS Selector Generator is published under the MIT license.

More Repositories

1

css-selector-generator-benchmark

benchmark for various JavaScript libraries for generating CSS selectors
HTML
178
star
2

fecal

Simple JavaScript library for people who frequently mistype Array methods `pop()`, `shift()` and `unshift()`.
JavaScript
36
star
3

UrlMatch

JavaScript object that provides URL matching functionality using patterns similar to what is used in extensions in Google Chrome.
JavaScript
28
star
4

workshop-js-principles

Podklady pre účastníkov školenia Princípy JavaScriptu.
JavaScript
26
star
5

koderske-testy

24
star
6

Savedeo-Extension

Browser extension that allows you to easily download videos from popular video sites (e.g. YouTube, Vimeo, etc.). Works with Google Chrome and Mozilla Firefox.
CoffeeScript
13
star
7

isvisible

Cross-browser function that checks if an element is visible.
JavaScript
12
star
8

github-issues-extension

Browser extension that adds handy tweaks for issues at GitHub.
CoffeeScript
10
star
9

firefox-addon-snippets

Firefox Addon Snippets
JavaScript
10
star
10

angle-js

Simple JavaScript library for working with angles.
JavaScript
7
star
11

workshop-vue-basics

Podklady k školeniu Vue.js prakticky
Vue
7
star
12

develcz2013

Podklady k prednáške na Devel.cz 2013
JavaScript
7
star
13

workshop-scope-closure

Unconventional slides for a workshop about scope and closure in Javascript.
JavaScript
7
star
14

frontendisti-npm

JavaScript
6
star
15

cookie-manager

Reusable module for cookie management in Firefox SDK (Jetpack).
JavaScript
6
star
16

workshop-automation

Podklady pre účstníkov kurzu "Automatizace s Grunt, Bower, Yeoman"
JavaScript
6
star
17

Mouse-Pointer-Double

Simple Chrome extension that creates duplicate of mouse pointer on a page. It is intended to use with Chromecast, so that you can see the mouse on the projected page.
CoffeeScript
6
star
18

workshop-js-tools

Podklady pre účastníkov školenia Nástroje JavaScriptu.
JavaScript
5
star
19

talk-2021-09-22-webexpo-codemod

JavaScript
5
star
20

devfest2012

Praktické ukážky kódu rozšírení pre Chrome prezentované na DevFest 2012 v Prahe
JavaScript
5
star
21

develcz-2017-tree-shaking

Podklady k prednáške pre konferenciu Devel 2017.
JavaScript
4
star
22

event-bridge

Bridge object for cross-browser working with events.
JavaScript
4
star
23

chrome-extension-snippets

Chrome extension snippets
JavaScript
4
star
24

webinar-webpack

JavaScript
3
star
25

export-music-list-extension

Browser extension that exports list of all songs from a library in Google Music.
CoffeeScript
3
star
26

2021-05-29-frontendisti-eslint

Podklady k prednáške na konferencii Frontendisti.
JavaScript
3
star
27

the-box

JS objects for working with DOM boxes.
JavaScript
3
star
28

chrome-flags

JavaScript
3
star
29

2022-webexpo-async

JavaScript
3
star
30

javascript-snippets

Collection of handy JavaScript code snippets.
JavaScript
3
star
31

iselement

Utility function that returns `true` if referenced object is DOM element.
JavaScript
2
star
32

update-json

NodeJS module for updating JSON files.
JavaScript
2
star
33

browser-extension-czech-months

Browser extension that adds normal translation to Czech month names.
JavaScript
2
star
34

uuid4

Generator and validator for Universally Unique Identifier v4 (random).
JavaScript
2
star
35

parse-relative-time

Parse simple relative time in human readable format to milliseconds.
JavaScript
2
star
36

intersectarrays

JavaScript function, that creates array containing values, that are present in all provided arrays.
CoffeeScript
2
star
37

browser-extension-mimi-tourette

JavaScript
2
star
38

get-nested-property

Get specific property of nested object, without the need for checking each step separately.
JavaScript
2
star
39

workshop-vue-2019-11-22

Vue
1
star
40

identify-element

A simple way to uniquely identify an HTML element.
JavaScript
1
star
41

workshop-till

JavaScript
1
star
42

workshop-testing

JavaScript
1
star
43

barcamp-hk-2016

Podklady k prednáške pre Barcamp Hradec Králové 2016
JavaScript
1
star
44

webinar-vue

Vue
1
star
45

config-mask

Helper that takes care of validating, sanitizing and coercing of complex config objects.
JavaScript
1
star
46

webinar-vue3

Vue
1
star
47

keyboard-visualiser

Sample project for JavaScript tools workshop
JavaScript
1
star
48

webinar-test-tools-js

JavaScript
1
star
49

expose

JavaScript helper for exposing objects to global namespace.
CoffeeScript
1
star
50

loger

Very simple loger for NodeJS.
JavaScript
1
star
51

carve

JavaScript
1
star
52

style-properties

JavaScript library for getting information about element style properties in unified and usable format.
JavaScript
1
star
53

2023-10-12-frontkon-typescript-bez-typescriptu

JavaScript
1
star
54

eslint-config

JavaScript
1
star
55

talk-2019-10-16-frontendisti

Podklady k prednáške na minikonferencii Frontendisti, 16.10.2019 v Slevomat.cz
Vue
1
star