- Print
- DarkLight
Using CSS selectors effectively
When testing web applications, you will often use CSS selectors to select elements.
Most of the time, you will not be aware of the CSS selector when using Autify Recorder to record [Scenarios]. However, when using the [Locator] or [JS Step] , there are times when you will need to write a CSS selector.
As explained in the [Locator] article, you can easily obtain a CSS selector for a given element by using Developer Tools on Google Chrome. However, the CSS selector obtained from Developer Tools may not work correctly in the [Locator] or [JS Step] (the details are explained below).
In this article, you will learn about how to select a CSS selector.
1. Basic CSS Selectors
This section outlines some of the most commonly used CSS selectors for selecting basic elements.
1.1 Basic selectors
Selection method | Example |
---|---|
Select by tag | div, a |
Select by class | .main, .sub |
Select by id | #a123, #b456 |
Select with a combination of tag, class, and id | div#a123.main, a.sub |
1.2 Frequently used selectors
Selection method | Example |
---|---|
Descendant element | .main .sub, div a |
Immediate child element | .main > .sub, div > a |
First child element | div:first-child |
Last child element | div:last-child |
Nth child element | li:nth-child(n) |
1.3 Good to know selectors
Selection method | Example |
---|---|
Select by an attribute | a[href="https://example.com/index.html"], p[class="main"] |
Elements with a partially matching attribute | a[href*="example.com"], p[class*="ai"] |
Elements with an attribute that matches at the beginning | a[href^="https://"], p[class^="ma"] |
Elements with an attribute that matches at the end | a[href$="index.html"], p[class$="in"] |
Disabled state | input:disabled, textarea:disabled |
1.4 Selectors related to forms
Selection method | Example |
---|---|
Text entry field | input[type="text"] |
text area | textarea |
Drop-down (select box) | select |
Nth option in a drop-down list | option:nth-child(n) |
Checkbox | input[type="checkbox"] |
Radio button | input[type="radio"] |
Checkboxes or radio button is checked | input[type="checkbox"]:checked, input[type="radio"]:checked |
Submit button | input[type="submit"] |
Disabled state | input[type="text"]:disabled |
2. How to use the CSS selector effectively
With CSS selectors, there can be more than one way to select an element. In automated testing, it’s important to select a method that:
- reflects your intentions,
- can identify the target without ambiguity,
- is concise and does not break easily (is resistant to changes in page structure)
even when there is more than one way to select.
Below, we look at how to write a CSS selector that selects <li>Hello! C2</li> in a page with the following HTML structure:
<html>
<body>
...
<div class="aaaaa ccccc">
...
<div id="#bbbbb">
...
<section class="ccccc">
...
<ul>
<li>Hello! A1</li>
<li>Hello! A2</li>
<li>Hello! A3</li>
</ul>
<ul>
<li>Hello! B1</li>
<li>Hello! B2</li>
<li>Hello! B3</li>
</ul>
<ul>
<li>Hello! C1</li>
<li>Hello! C2</li>
<li>Hello! C3</li>
</ul>
...
</section>
...
</div>
...
</div>
...
</body>
</html>
The HTML hierarchy is shown below.
2.1. Select all the immediate parent elements in order along the HTML hierarchy
If you were to select the immediate parent elements until the tag in order of the HTML hierarchy of the target element, it would look like this:
body > div.aaaaa.ccccc > div#bbbbb > section.ccccc > ul:last-child > li:nth-child(2)
This is not versatile because the ancestor elements and class/id are selected too strictly. Following situations may occur when managing a website:
- Change in class/id
Example: the style of <div class="aaaaa ccccc"> changed to <div class="aaaaa bbbbb"> because of a design change. - Change in HTML structure
Example: <li>Hello! C0</li> was added before <li>Hello! C2</li>, making it the third item instead of the second.
These situations have a high chance of breaking CSS selector and it can no longer select the target element.
2.2. Select by tag only
Consider a CSS selector that selects all the immediate parent elements in order along the HTML hierarchy. If you omit the class/id of the <div> tag and <section> tag and select only using elements, it would look like this:
body > div > div > section > ul:last-child > li:nth-child(2)
In this case, “div > div > section” becomes a condition for “<div> tag and <section> tag that match the HTML hierarchy.”
If the class/id of your website tends to change frequently, you may want to omit the class/id of the <div> tag and <section> tag and select by elements only.
2.3. Select by class/id only
Elements that have a class/id can also be written only with class/id.
Consider a CSS selector which selects all the immediate parent elements in order along the HTML hierarchy. If you select <div> tags and <section> tags that have a class/id by only using class/id, it would look like this:
body > .aaaaa.ccccc > #bbbbb >.ccccc > ul:last-child > li:nth-child(2)
In this case, “.aaaaa.ccccc > #bbbbb >.ccccc” is a condition for “all elements with the corresponding class/id set that match the HTML hierarchy”.
2.4. Select the immediate child element
div.aaaaa > section > ul:last-child > li:nth-child(2)
With above CSS selector, <div class="aaaaa"> does not have a <section> tag which could be a child element immediately under it. Therefore, there is no element that is selected by this CSS selector.
2.5. Select the descendant element
In “select the immediate child element”, <div class="aaaa"> did not have a <section> tag immediately under it, so there was no element to be selected. However, by changing “div.aaaaa > section” (select the immediate child element) to “div.aaaaa section” (select the descendant element), there is a <section> tag that is a descendant element of <div class="aaaaa">.
div.aaaaa section > ul:last-child > li:nth-child(2)
In the above CSS selector, the target element is the second <li> element immediately under the last <ul> out of the <ul> descendant elements of the <div> tag with class name "aaaaa". The selected target is <li>Hello! C2</li>.
2.6. Shorten the CSS selector
As mentioned above, the CSS selector shown in “Select all the immediate parent elements in order along the HTML hierarchy,” there is has a high risk of it not being able to select the target element, such as when the HTML structure changes due to page update or when class/id changes due to design change.
You can reduce this risk by keeping your CSS selectors short and simple.
Let’s take the CSS selector to select all the immediate parent elements in order along the HTML hierarchy. It can be broken down based on the selection condition.
body > div.aaaaa.ccccc > div#bbbbb > section.ccccc > ul:last-child > li:nth-child(2)
- body > div.aaaaa.ccccc > div#bbbbb > section.ccccc > ul > li
- The target are elements that match the HTML hierarchy.
- ul:last-child
- The target is the last <ul> tag out of the <ul> tags that match condition 1.
- li:nth-child(2)
- The target is the second <li> tag out of the </li><li> tags that match condition 1.
HTML hierarchy 1 can be shortened as long as the target element can be selected.
For example, if the <section> tag exists only in this part of the page, <section> is a unique element in this page. Therefore, the CSS selector that selects the parent elements up to the <section> tag will work (shown below).
section > ul:last-child > li:nth-child(2)
In the case of the above selector, the target element is the second <li> element immediately under the last <ul> out of the children <ul> immediately under <section>. The selected target is <li>Hello! C2</li>.
Note that W3C advises that the value of the id attribute must be unique within a single document. If an element has an id, it is likely to be unique within a page.
2.7. If you shorten the CSS selector too much...
Please be aware that shortening the CSS selector too much may cause the target element to be ambiguous, or the target element cannot be selected.
2.7.1. There is more than one selected target (1)
section > ul > li:nth-child(2)
In the above selector, the target element is the second <li> elements immediately under the children <ul> immediately under <section>. The selected targets are <li>Hello! A2</li>, <li>Hello! B2</li>, <li>Hello! C2</li>.
2.7.2. There is more than one selected target (2)
section li
In the above selector, the target elements are <section>’s descendant elements <li>, so the selected targets are </li><li>Hello! A1</li>, <li>Hello! A2</li>, <li>Hello! A3</li>, <li>Hello! B1</li>, <li>Hello! B2</li>, <li>Hello! B3</li>, <li>Hello! C1</li>, <li>Hello! C2</li>, <li>Hello! C3</li>.
2.7.3. Target does not exist
section > li:nth-child(2)
In the above selector, the target element is the second immediate child element <li> of <section>, so there is no target element.
2.7.4. An unintended element is selected
section li:nth-child(2)
In the above selector, the target element is the second <li> of <section>’s descendant elements. Therefore, the target element is <li>Hello! A2</li>.