DEV Community

Cover image for Generate a CSS selector path of a DOM element.
Aniket Chauhan
Aniket Chauhan

Posted on

Generate a CSS selector path of a DOM element.

The task is to generate a CSS selector path of DOM element by implementation of 'generateSelector' function.

Prerequisites: You must be aware of the basics of HTML, CSS and JavaScript.

Approach:

  1. First of all, you need to create an index.html file that consists of any markup code like shown in example code.
  2. Create an app.js file that generate unique CSS selector as given below in the code.
  3. In the app.js file, when any element is clicked, it will shown in browser console and the generated selector shown on web interface.

Example: In this example, In order to get that selectors are unique, We will use :nth-of-type Selectors. Click on the element to see selector.

Note: This function creates a long, but quite practical unique selector, works quickly.

Comment below if you have any query. I hope you’ll find this article helpful, Thank you for reading :)

Oldest comments (8)

Collapse
 
supportic profile image
Supportic

Open Devtools -> select element in DOM -> right click: copy -> copy selector. Voila. :)
But yeah if you want dynamically create CSS selectors maybe not onclick but for something else, the functions might come in handy.

Collapse
 
aniket_chauhan profile image
Aniket Chauhan

Yeah, true. But for demonstrate purpose I used click event 😅

Collapse
 
grahamthedev profile image
GrahamTheDev • Edited

Had to bookmark this as it could be a great base for a library I work on and I like your implementation.

Here is my implementation, but it generates the the Xpath to the item instead of a unique selector.

One thing you should steal is the returning early if the item has an ID (as obviously the ID should be unique) just to save on selector complexity.

Collapse
 
disgustingdev profile image
disgusting-dev

Fella, if you are about to create xPath generator, I suggest you to create browser extension for this - I believe there will be a lot of those QA guys who need as fast as possible to get in clipboard such an xpath for e2e testing (yes, I'm talking about those who don't use test ids) - and much better if it defines id or data-id etc. of element and minimize your path just to it

Collapse
 
grahamthedev profile image
GrahamTheDev • Edited

It already uses the id if you look at the code, first thing it checks for and returns early if found.

Plus this is used as part of an analytics package to track clicks, the being able to click on things is just to demonstrate.

If you wanted you could easily turn it into a bookmarklet and have the ID copied to the clipboard, no need to build a browser extension for something so simple, especially when you can get the Xpath with developer tools really easily.

Collapse
 
aniket_chauhan profile image
Aniket Chauhan • Edited

Thanks :)
Here is some reference: stackoverflow, sitepoint.
I will try it.

Collapse
 
locnguyen2000 profile image
LocNguyen2000 • Edited

I fix your code like a bit so that it also show className and id

function generateSelector(context) {
    let index, pathSelector, localName;

    if (context == "null") throw "not an dom reference";
    // call getIndex function
    index = getIndex(context);

    while (context.tagName) {
        // selector path

        const className = context.className
        const idName = context.id

        pathSelector = context.localName + 
                        ( className ? `.${className}` : "") + 
                        ( idName ? `#${idName}` : "") +
                        (pathSelector ? ">" + pathSelector : "");

        context = context.parentNode;
    }
    // selector path for nth of type
    pathSelector = pathSelector + `:nth-of-type(${index})`;
    return pathSelector;
}

// get index for nth of type element
function getIndex(node) {
    let i = 1;
    let tagName = node.tagName;

    while (node.previousSibling) {
    node = node.previousSibling;
    if (
        node.nodeType === 1 &&
        tagName.toLowerCase() == node.tagName.toLowerCase()
    ) {
        i++;
    }
    }
    return i;
}

// load document
document.addEventListener("DOMContentLoaded", () => {
    // click on element to get output
    document.body.addEventListener("click", (e) => {
        // let selector = document.querySelector(".selector");
        // selector output
        let output = generateSelector(e.target);

        // selector.innerHTML = `<strong>Selector:</strong> ${output}`;

        // element that you select
        let element = document.querySelector(output);
        console.log(output);                
        console.log("Element:", element);                
    });
});
Enter fullscreen mode Exit fullscreen mode
Collapse
 
aniket_chauhan profile image
Aniket Chauhan

That's great!🤙🏻