CssSelectors - Not only for styling
As we all (Selenium users) know, There are 8 locator types that allow us to identify WebElements in our AUT. (And now, relative locators were added in the latest Selenium 4 release). In this post, I want to talk a little bit more about CSS Selectors. CSS Selectors are highly useful and powerful, and yet, for many Selenium users, it will often be the last choice. Perhaps, from lack of exposure to its capabilities.
Let's start with defining what is a CSS Selector
First, just to be in sync, CSS stands for Cascading Style Sheet.
Little that we know, but a CSS Selector is actually a part of the CSS Ruleset that allows Web Developers to style a particular content of the DOM. In other words, by using CSS Selectors, we can "tell" the browser which HTML elements should be selected to have the CSS rule applied to them.
What is a CSS Rule?
A CSS rule is a statement that defines the style of one or more elements on the webpage. It consists of a selector and a declaration, and it will apply for all instances of an element.
Let's take a look at a basic example:
As we can see in the above screenshot, we have 2 divs containing 2 different buttons.
According to the CSS rules:
- All "divs" receive a 50 pixel margin.
- A button with a "btn" ID is defined to be with a yellow background.
- A button with a "btn2" ID is defined to be with a pink background.
- All web elements type "button" are with a pre-defined height and width.
How is it related to Test Automation?
In test automation, we are provided with the option of identifying web elements using CSS Selectors. By better understanding them, we can enrich our professional toolbox and learn more flexible ways to work.
So let's take a look at some helpful examples
Using Css to identify an element by a tag name, an attribute and it’s value:
CSS: tag_name[<attribute_name>='<attribute_value>']
e.g.: "input[type='text']"
In CSS, we can also use the # notation to select the id. Let’s use the same HTML example:
CSS: #id or just tagname#id
e.g.: "input#name" or just "#name"
We can also use the . notation to select the class name:
CSS: tagname.classname
e.g.: "input.name" or just ".name"
In Selenium CSS selectors allow us to navigate through elements to select a specific target using nth-child or nth-of-type.
In a nutshell the :nth-child selector allows you to select one or more elements based on their source order, in styling it is used to style content based on its relationship with parent and sibling elements. For example, if we want to select the 4th element on the list:
CSS: #id <tagname>:nth-of-type()
e.g.: "#vehicles li:nth-of-type(4)"
In this case, this selector will point to "Bicycle".
You can also select an nth-child without specifying its type:
CSS: #id *:nth-child()
e.g.: "#vehicles *:nth-child(4)"
In the above example, I used the * wildcard. There are different ways to use them. For example, you can use them to query the document for a specific property or search for partial string matches.
To match an id substring:
CSS: tagname[id*=”id_substring”]
e.g.: "button[id*='tn1']"
To match an id prefix:
CSS: tagname[id^=”id_prefix”]
e.g.: "button[id^='btn']"
To match a suffix:
CSS: tagname[id$=”id_suffix”]
e.g.: "button[id$='1']"
If needed, with CssSelectors we can also choose to specify two properties by which Selenium will find our element.
CSS: tagname[attribute='value'][attribute='value']
e.g.: "input[name='myInput'][type='text']"
Or, we can choose to filter out all of the password type input elements:
CSS: tagname[attribute='value']:not([attribute='value'])
e.g.: "input[name='myInput']:not([type='password'])"
In conclusion...
CSS selectors are a powerful and useful tool. There is a lot of information online, including:
Use it wisely! ;)
Greetings from Germany,
ReplyDeleteThere is few typos, besides, looks cool.
Fixed, thank you!
DeleteGood stuff! Been using those for a while now, quite useful. But still not as powerful as XPath. However, nice to have options!
ReplyDeleteGreat reading your bblog post
ReplyDelete