JavaScript object that creates a unique CSS selector for a given DOM element.
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.
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';
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);
});
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(targtElement)
</script
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)"
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"
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"
If you want to ignore some selectors, you can put them on the blacklist. Blacklist is an array that can contain either regular expressions, or strings. In strings, you can use an asterisk (*
) as a wildcard that will match any number of any characters.
<body>
<!-- targetElement -->
<div class="firstClass secondClass"></div>
</body>
getCssSelector(targetElement, {blacklist: ['.firstClass']});
// ".secondClass"
getCssSelector(targetElement, {blacklist: ['.first*']});
// ".secondClass"
getCssSelector(targetElement, {blacklist: [/first/]});
// ".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'
]
}
)
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"
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.
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.
This option will add tag selector type to every selector:
<body>
<!-- targetElement -->
<div class="myElement"></div>
</body>
getCssSelector(targetElement, {includeTag: true});
// "div.myElement"
Generates unique CSS selector for an element.
element
Elementcustom_options
css_selector_generator_options? (optional, default{}
)
Returns string
Utility function to make subsequent calls shorter.
Returns {foundElement: Element, selector: string}
Type: Object
selectors
Array<css_selector_type>? List of selector types to use. They will be prioritised by their order.whitelist
Array<(RegExp | string)>? List of selectors that should be prioritised.blacklist
Array<(RegExp | string)>? List of selectors that should be ignored.root
Element? Root element inside which the selector will be generated. If not set, the document root will be used.combineWithinSelector
boolean? If set totrue
, the generator will test combinations of selectors of single type (e.g. multiple class selectors).combineBetweenSelectors
boolean? If set totrue
, the generator will try to test combinations of selectors of different types (e.g. tag + class name).includeTag
boolean? If set totrue
, all generated selectors will include the TAG part. Even if tag selector type is not included inselectors
option.
Type: ("id"
| "class"
| "tag"
| "attribute"
| "nthchild"
| "nthoftype"
)
Instead of creating a class and then calling the getSelector()
method, now you just call a function getCssSelector()
and provide it with element reference and options:
// v1
const mySelectorGenerator = new CssSelectorGenerator({/* custom options */});
mySelectorGenerator.getSelector(elementReference);
// v2
getCssSelector(elementReference, {/* custom options */});
- Options
id_blacklist
,class_blacklist
andattribute_blacklist
are replaced with singleblacklist
option, which is now applied to all selector types. - Option
attribute_whitelist
is replaced withwhitelist
option, which is now applied to all selector types. - Option
prefix_tag
is renamed toincludeTag
. - Option
quote_attribute_when_needed
is removed. The attribute selectors are quoted automatically.
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 riki@fczbkk.com
CSS Selector Generator is published under the MIT license.