{"id":24445732,"url":"https://github.com/fczbkk/css-selector-generator","last_synced_at":"2025-10-07T01:26:10.117Z","repository":{"id":13243047,"uuid":"15927843","full_name":"fczbkk/css-selector-generator","owner":"fczbkk","description":"JavaScript object that creates unique CSS selector for given element.","archived":false,"fork":false,"pushed_at":"2025-05-12T21:06:06.000Z","size":7576,"stargazers_count":561,"open_issues_count":9,"forks_count":93,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-05-12T22:23:41.248Z","etag":null,"topics":["css","css-selector","dom","element"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fczbkk.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-01-15T07:15:00.000Z","updated_at":"2025-05-12T21:06:10.000Z","dependencies_parsed_at":"2023-10-13T13:03:09.247Z","dependency_job_id":"c74c05cc-f36d-45d7-ab8d-babc6fd9b6d4","html_url":"https://github.com/fczbkk/css-selector-generator","commit_stats":{"total_commits":594,"total_committers":14,"mean_commits":42.42857142857143,"dds":0.4427609427609428,"last_synced_commit":"3d31ef880cfef48496331b6d7d847b9e276a97c0"},"previous_names":[],"tags_count":53,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fczbkk%2Fcss-selector-generator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fczbkk%2Fcss-selector-generator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fczbkk%2Fcss-selector-generator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fczbkk%2Fcss-selector-generator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fczbkk","download_url":"https://codeload.github.com/fczbkk/css-selector-generator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253832487,"owners_count":21971274,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["css","css-selector","dom","element"],"created_at":"2025-01-20T23:30:14.752Z","updated_at":"2025-10-07T01:26:10.106Z","avatar_url":"https://github.com/fczbkk.png","language":"TypeScript","readme":"# CSS Selector Generator\n\nJavaScript object that creates a unique CSS selector for a given DOM element or multiple DOM elements.\n\nIt also generates shorter selectors and is faster and/or more robust than many other libraries - see this [comparison](https://github.com/fczbkk/css-selector-generator-benchmark) and select the best alternative for your use case.\n\n## Install\n\nAdd the library to your project via NPM or Yarn.\n\n```shell\nnpm install css-selector-generator\nyarn add css-selector-generator\n```\n\nThen include it in your source code:\n\n```javascript\nimport { getCssSelector } from \"css-selector-generator\";\n```\n\n## How to use\n\nSimplest way to use it is to provide an element reference, without any options.\n\n```html\n\u003cbody\u003e\n  \u003c!-- targetElement --\u003e\n  \u003cdiv class=\"myElement\"\u003e\u003c/div\u003e\n\u003c/body\u003e\n```\n\n```javascript\ngetCssSelector(targetElement);\n// \".myElement\"\n```\n\nTypical example is to create a selector for any element that the user clicks on:\n\n```javascript\n// track every click\ndocument.body.addEventListener(\"click\", function (event) {\n  // get reference to the element user clicked on\n  const element = event.target;\n  // get unique CSS selector for that element\n  const selector = getCssSelector(element);\n  // do whatever you need to do with that selector\n  console.log(\"selector\", selector);\n});\n```\n\n### Usage without NPM\n\nIf 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:\n\n```html\n\u003c!-- link the library --\u003e\n\u003cscript src=\"build/index.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n\tCssSelectorGenerator.getCssSelector(targetElement)\n\u003c/script\n```\n\n### Usage with virtual DOM (e.g. JSDOM)\n\nIf 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:\nhttps://github.com/jsdom/jsdom/wiki/Don't-stuff-jsdom-globals-onto-the-Node-global\n\n### Multi-element selector\n\nThis 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:\n\n```html\n\u003cbody\u003e\n  \u003c!-- firstElement --\u003e\n  \u003cdiv class=\"aaa bbb\"\u003e\u003c/div\u003e\n  \u003c!-- secondElement --\u003e\n  \u003cspan class=\"bbb ccc\"\u003e\u003c/span\u003e\n\u003c/body\u003e\n```\n\n```javascript\ngetCssSelector([firstElement, secondElement]);\n// \".bbb\"\n```\n\nIf it is not possible to construct single selector for all elements a standalone selector for each element will be generated:\n\n```html\n\u003cbody\u003e\n  \u003c!-- firstElement --\u003e\n  \u003cdiv\u003e\u003c/div\u003e\n  \u003c!-- secondElement --\u003e\n  \u003cspan\u003e\u003c/span\u003e\n\u003c/body\u003e\n```\n\n```javascript\ngetCssSelector([firstElement, secondElement]);\n// \"div, span\"\n```\n\n### Fallback\n\n`getCssSelector` determines the shortest CSS selector for parent -\u003e child relationship, from the input Element until the Root Element.\n\nIf there is no _unique_ selector available for any of these relationships (parent -\u003e child), a fallback of `*` will be used for this relationship.\n\n    #wrapper \u003e * \u003e div \u003e .text\n\nIn some cases, this selector may not be unique (e.g. `#wrapper \u003e * \u003e div \u003e *`). In this case, it will fall back to an entire chain of `:nth-child` selectors like:\n\n    \":nth-child(2) \u003e :nth-child(4) \u003e :nth-child(1) \u003e :nth-child(12)\"\n\n## Options\n\n- [`selectors`](#selector-types)\n- [`root`](#root-element)\n- [`blacklist`](#blacklist)\n- [`combineWithinSelector`](#combine-within-selector)\n- [`combineBetweenSelectors`](#combine-between-selectors)\n- [`includeTag`](#include-tag)\n- [`maxCombinations`](#max-combinations)\n- [`maxCandidates`](#max-candidates)\n- [`useScope`](#use-scope)\n\n### Selector types\n\nYou can choose which types of selectors do you want to use:\n\n```html\n\u003cbody\u003e\n  \u003c!-- targetElement --\u003e\n  \u003cdiv class=\"myElement\"\u003e\u003c/div\u003e\n\u003c/body\u003e\n```\n\n```javascript\ngetCssSelector(targetElement, { selectors: [\"class\"] });\n// \".myElement\"\ngetCssSelector(targetElement, { selectors: [\"tag\"] });\n// \"div\"\n```\n\nOrder of selector types defines their priority:\n\n```javascript\ngetCssSelector(targetElement, { selectors: [\"class\", \"tag\"] });\n// \".myElement\"\ngetCssSelector(targetElement, { selectors: [\"tag\", \"class\"] });\n// \"div\"\n```\n\nValid selector types are:\n\n- `id`\n- `class`\n- `tag`\n- `attribute`\n- `nthchild`\n- `nthoftype`\n\n### Root element\n\nYou can define root element, from which the selector will be created. If root element is not defined, document root will be used:\n\n```html\n\u003cbody\u003e\n  \u003cdiv class=\"myRootElement\"\u003e\n    \u003c!-- targetElement --\u003e\n    \u003cdiv class=\"myElement\"\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/body\u003e\n```\n\n```javascript\ngetCssSelector(targetElement);\n// \".myRootElement \u003e .myElement\"\ngetCssSelector(targetElement, {\n  root: document.querySelector(\".myRootElement\"),\n});\n// \".myElement\"\n```\n\n### Blacklist\n\nIf 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.\n\nIn **strings**, you can use an asterisk (`*`) as a wildcard that will match any number of any characters.\n\n**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.\n\n```html\n\u003cbody\u003e\n  \u003c!-- targetElement --\u003e\n  \u003cdiv class=\"firstClass secondClass\"\u003e\u003c/div\u003e\n\u003c/body\u003e\n```\n\n```javascript\ngetCssSelector(targetElement, { blacklist: [\".firstClass\"] });\n// \".secondClass\"\ngetCssSelector(targetElement, { blacklist: [\".first*\"] });\n// \".secondClass\"\ngetCssSelector(targetElement, { blacklist: [/first/] });\n// \".secondClass\"\ngetCssSelector(targetElement, {\n  blacklist: [(input) =\u003e input.startsWith(\".second\")],\n});\n// \".secondClass\"\n```\n\nYou can target selectors of any types using the blacklist.\n\n```javascript\ngetCssSelector(targetElement, {\n  blacklist: [\n    // ID selector\n    \"#forbiddenId\",\n    // class selector\n    \".forbiddenClass\",\n    // attribute selector\n    \"[forbidden-attribute]\",\n    // tag selector\n    \"div\",\n  ],\n});\n```\n\n### Whitelist\n\nSame as `blacklist` option, but instead of ignoring matching selectors, they will be prioritised.\n\n```html\n\u003cbody\u003e\n  \u003c!-- targetElement --\u003e\n  \u003cdiv class=\"firstClass secondClass\"\u003e\u003c/div\u003e\n\u003c/body\u003e\n```\n\n```javascript\ngetCssSelector(targetElement, { whitelist: [\".secondClass\"] });\n// \".secondClass\"\ngetCssSelector(targetElement, { whitelist: [\".second*\"] });\n// \".secondClass\"\ngetCssSelector(targetElement, { whitelist: [/second/] });\n// \".secondClass\"\n```\n\n### Combine within selector\n\nIf 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.\n\n```html\n\u003cbody\u003e\n  \u003c!-- targetElement --\u003e\n  \u003cdiv class=\"aaa bbb\"\u003e\u003c/div\u003e\n  \u003cdiv class=\"aaa ccc\"\u003e\u003c/div\u003e\n  \u003cdiv class=\"bbb ccc\"\u003e\u003c/div\u003e\n\u003c/body\u003e\n```\n\n```javascript\ngetCssSelector(targetElement, { combineWithinSelector: false });\n// \"body \u003e :nth-child(1)\" - in this case no single class name is unique\ngetCssSelector(targetElement, { combineWithinSelector: true });\n// \".aaa.bbb\"\n```\n\nThis option is set to `true` by default. It can be set to `false` for performance reasons.\n\n### Combine between selectors\n\nIf 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.\n\n```html\n\u003cbody\u003e\n\t\u003c!-- targetElement --\u003e\n\t\u003cdiv class=\"aaa\"\u003e\u003c/div\u003e\n\t\u003cdiv class=\"bbb\"\u003e\u003c/div\u003e\n\t\u003cp class=\"aaa\"\u003e\u003c/p\u003e\n\u003c/body\u003e\n```\n\n```javascript\ngetCssSelector(targetElement, { combineBetweenSelectors: false });\n// \"body \u003e :nth-child(1)\" - in this case no single class name or tag name is unique\ngetCssSelector(targetElement, { combineBetweenSelectors: true });\n// \"div.aaa\"\n```\n\nThis option is set to `true` by default. It can be set to `false` for performance reasons.\n\n### Include tag\n\nThis option will add tag selector type to every selector:\n\n```html\n\u003cbody\u003e\n  \u003c!-- targetElement --\u003e\n  \u003cdiv class=\"myElement\"\u003e\u003c/div\u003e\n\u003c/body\u003e\n```\n\n```javascript\ngetCssSelector(targetElement, { includeTag: true });\n// \"div.myElement\"\n```\n\n### Max combinations\n\nThis 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.\n\nIn 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.\n\n```javascript\ngetCssSelector(targetElement, { maxCombinations: 100 });\n```\n\n### Max candidates\n\nPerformance optimization option, similar to `maxCombinations`. This does limit a total number of selector candidates for each element.\n\nYou 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.\n\n```javascript\ngetCssSelector(targetElement, { maxCandidates: 100 });\n```\n\n### Use scope\n\n**Experimental feature** - *This will probably be turned on by default and the option will be removed, after I thoroughly evaluate that it produces valid selectors in all use cases.*\n\nIf set to `true` and the [`root` option](#root-element) is provided, the fallback selectors will be created relative to the `root` element using the `:scope` pseudo-class.\n\nFor example, if you have the following HTML structure:\n\n```html\n\u003chtml\u003e\n  \u003cbody\u003e\n    \u003cdiv\u003e\n      \u003cdiv\u003e\u003c!-- haystackElement --\u003e\n        \u003cdiv\u003e\n          \u003cdiv\u003e\u003c!-- needleElement --\u003e\u003c/div\u003e\n        \u003c/div\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nIf you generate the selector **without** the `useScope` option:\n\n```javascript\ngetCssSelector(needleElement, {\n  root: haystackElement,\n  useScope: false,\n});\n```\n\n...it will produce this fallback selector:\n\n```\n:root \u003e :nth-child(1) \u003e :nth-child(1) \u003e :nth-child(1) \u003e :nth-child(1) \u003e :nth-child(1)\n```\n\n... where the selectors correspond with these elements:\n\n```\n:root             -\u003e \u003chtml\u003e\n\u003e :nth-child(1)   -\u003e   \u003cbody\u003e\n\u003e :nth-child(1)   -\u003e     \u003cdiv\u003e\n\u003e :nth-child(1)   -\u003e       \u003cdiv\u003e \u003c!-- haystackElement --\u003e\n\u003e :nth-child(1)   -\u003e         \u003cdiv\u003e\n\u003e :nth-child(1)   -\u003e           \u003cdiv\u003e \u003c!-- needleElement --\u003e\n```\n\nBut if you generate the selector **with** the `useScope` option:\n\n```javascript\ngetCssSelector(needleElement, {\n  root: haystackElement,\n  useScope: true,\n});\n```\n\n...it will produce this fallback selector:\n\n```:scope \u003e :nth-child(1) \u003e :nth-child(1)```\n\n... where the selectors correspond with these elements:\n\n```\n:scope            -\u003e \u003cdiv\u003e \u003c!-- haystackElement --\u003e\n\u003e :nth-child(1)   -\u003e   \u003cdiv\u003e\n\u003e :nth-child(1)   -\u003e     \u003cdiv\u003e \u003c!-- needleElement --\u003e\n```\n\n## Bug reports, feature requests and contact\n\nIf you found any bugs, if you have feature requests or any questions, please, either [file an issue on GitHub][1] or send me an e-mail at [riki@fczbkk.com][2]\n\n## License\n\nCSS Selector Generator is published under the [MIT license][3].\n\n[1]: https://github.com/fczbkk/css-selector-generator/issues\n[2]: mailto:riki@fczbkk.com?subject=CSSSelectorGenerator\n[3]: https://github.com/fczbkk/css-selector-generator/blob/master/LICENSE\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffczbkk%2Fcss-selector-generator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffczbkk%2Fcss-selector-generator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffczbkk%2Fcss-selector-generator/lists"}