Introduction
Learning and mastering a powerful location strategy is a must in Selenium test automation. CSS and XPath are the most powerful location strategies as compared to the other location strategies available such as ID, name, class name, tag-name, link text and partial link text. Most of the test automation engineers are familiar with above location strategies.
Selenium 4 will have Relative locators. It is a friendly way to locate the elements with friendly terms (methods) like ‘near’, ‘above’ , ‘below’, ‘toLeftOf’ and ‘toRightOf’.
The intent of this blog post is to help Selenium test automation engineers, especially the beginners to understand the importance of mastering location strategies and set a path to master the CSS location strategy.
We have discussed XPath in detail in a separate blog post already and this blog post will limit to CSS location strategy.
At the beginning you will see the comparison of CSS and XPath in the context of Selenium test automation, practical usage of CSS and few pain points are shared in the next section. Number of CSS options available with syntax, HTML snippet and examples are discussed in the middle of the post. XPath to CSS conversion tools, CSS generating tools, validation tools, a game for practicing CSS are discussed at the later part of this blog post. A cheatsheet and a glossary are added to the end of the post.
We have referred a wide range of online resources, included lessons learned from our training programs and experience through test automation projects into this blog post.
We will continue to improve and update this post and share with the testing community. [ last updated on 05 Jan 2021]
Happy test automation!
What is CSS?
Cascading Style Sheets, fondly referred to as CSS, is a simple design language intended to simplify the process of making web pages presentable.
CSS handles the look and feel part of a web page. Using CSS, you can control the colour of the text, the style of fonts, the spacing between paragraphs, how columns are sized and laid out, what background images or colors are used, as well as a variety of other effects.
CSS is
CSS or XPath
CSS and XPath are the most popular, widely used and powerful location strategies within the Selenium test automation community. CSS has gained wider acceptance due to following reasons. (People in favor of CSS says)
- CSS more readable ( simpler )
- CSS is faster (especially in IE)
Those who are in favor of XPath says about its ability to transverse around the page where CSS cannot. XPath can traverse up and down the document tree. CSS can traverse only down to the DOM.
These claims may be already outdated. Some research demonstrates that there is no significant difference in speed of CSS and XPath executions.
Following is from Mozilla Developer Network Documentation
Mastering XPath and CSS is a good investments for the Selenium test automation engineers who wish to build their career around Selenium.
It is better to a use a single location strategy within a project for consistency.
Some gurus advice a hybrid approach. They use ID, name first and moving to CSS. XPath is used only when it is required.
Good Locators Are
In this section, we will discuss characteristics of a good location strategy. We shall select a best possible CSS from available options/syntax. A good location strategy should be
- Descriptive
- Resilient
- Shorter in length
- Unique (if you want to locate a single element)
Your CCS locator should have only one candidate element (Unique) when you want to target a single element using findElement method. It is easy to identify the element in the script easily when the CSS is descriptive. It should be possible to locate the element with given CSS when a test is run repeatedly in subsequent releases. CSS should be selected in such a way that it is valid even after the changes to the DOM. You will have multiple CSS options when you master CSS. A shorter CSS shall be selected to make it more readable in your test scripts.
Sample HTML
We will use the following HTML , a simple login form to explain the CSS syntax in most of the cases. This is extracted from our demo site.
Terminology
Let’s get familiar with mostly used terms in CSS syntax.
Locating elements with a known value
Following syntax can be used for locating elements with a known attribute value.
Syntax :
[attribute-name='attribute-value’]
Examples :
Let’s see how to locate the username field using the syntax.
- [id=’txtUsername’]
- [name=’txtUsername’]
- [type=’text’]
The third option should not be used if you want a select an element uniquely even though it is a valid syntax. There could be many such elements and Selenium will not be able to locate target element uniquely. Selenium will return the first element with the given CSS when findElement method is called.
As you know in real life we use unique names (or IDs) to locate a person in a group. As you know it is not possible to locate a person distinctly by name Mohammed in a muslim community. You will have to use some other name to locate a person uniquely.
If you are interested in all the elements with the common attribute you may use the syntax with findElements method and iterate through the elements.
Locating elements with known tag-name and an attributes
The following can be used for locating elements with a known tag-name and their attributes’ value.
Syntax:
tag-name[attribute-name='attribute-value']
Examples :
- input[id=’txtUsername’]
- input[name=’txtUsername’]
- input[type=’text’]
Note
- Attribute values should be enclosed with single or double quotes
- Escape character , back slash \ should be use when the value contains quotes
Javascript :: driver.findElement(By.css("input[id='txtUsername']")).sendKeys('Admin')
Java :: driver.findElement(By.cssSelector("input[id='txtUsername']")).sendKeys("Admin");
Python :: driver.find_element_by_css_selector("input[name='txtUsername']").send_keys("Admin")
Locating Elements by ID
In CSS # sign is used for locating the elements by the value of attribute-name ID.
Syntax :
tag-name#valueofID
or #valueofID
Examples :
- input#txtUsername
- #txtUsername
Locating Elements by a class name
You can locate target elements by one of the class name (value) in class attribute.
Syntax :
tag-name.className
or .className
Examples :
- input.button
- .button
Locating elements by multiple classes
Multiple classes can be separated by dots as in the following syntax
Syntax :
tag-name.
className1.className2….classNameN
or .className1.className2….classNameN
Examples :
- div.box.searchForm.toggleForm.
- box.searchForm
It is not required to provide all the class names. Ensure element is uniquely selected with minimum number of classes if you decide to use class names.
Locating Elements by class name and attribute
Syntax :
tag-name.className[attribute-name=’attribute-value’
]
or .className[attribute-name=’attribute-value’]
Examples :
- input.button[name=’Submit’]
- .button[name=’Submit’]
Locating Elements by multiple attributes
Sometimes it may not be possible to locate an element with a single attribute. In the real world, we have a similar issue. We cannot locate a person with just the first name or last name. We will have to use a combination of first name and last name to locate a person to locate a person without making any confusion.
Syntax :
tag-name[a-name1=’a-value1’][a-name2=’a-value2’] ..[a-nameN=’a-valueN’
]
or [a-name1=’a-value1’][a-name2=’a-value2’] ..[a-nameN=’a-valueN’]
Examples :
- input[id=’txtUsername’][name=’txtUsername’]
- [id=’txtUsername’][name=’txtUsername’]
It is not necessary to use multiple attributes if one attribute can be used for locating the target element(s) uniquely. You may not have to use more than two attributes to locate the target element(s) uniquely.
Locating Child Elements by Tag Name
We can locate direct child element(s) with respect to a known parent element using > character. An element could have zero, one or many child elements.
Syntax :
CSS-of-Parent
>
Element
CSS-of-Parent
>
*
Example :
- div#divUsername>input
- div#divUsername>*
In the first example we input element is selected. All children (input and span) will be selected when universal character * is used.
Locating descendant elements by tag-name
When space is given descendant elements of context elements are selected. It will select all elements inside a context element when universal character * is used.
Syntax :
CSS-of-Context-Element<space>tag-name
CSS-of-Context-Element<space>*
Examples :
- form input
- form *
Three(3) input elements inside the form element will be selected in the first example . All elements inside the form element will be selected in the second example.
Working with multiple candidates
Sometimes there will be more than one element for a given CSS. When you use findElement(By by) method , first element is selected by Selenium.
WebElement txtUsername=webDriver.findElement(By.cssSelector("form input"));
Important notes on using findElement and findElements
findElement method should not be used to look for non-present elements, use findElements(By) and assert zero-length response instead.
webDriver.findElement(By.cssSelector("form input")).size();
The findElement method will return a matching element or try again repeatedly until the timeout is reached.
findElement method will select the first element when there are multiple candidate elements for a given CSS. It will not wait for other possible elements with given CSS.
Use findElements(By by) method to get the ALL elements with given CSS.
List<WebElement> inputElements=webDriver.findElements(By.cssSelector("form input"));
Locating Nth child elements by an element name
This syntax can be used for selecting an element from a list of sibling elements by their position.
Syntax :
CSS-of-Context-Element<space>tag-name:nth-of-type(N)
CSS-of-Context-Element<space>*:nth-of-type(N)
Examples :
- form input:nth-of-type(1) Selects the first input element
- form input:nth-of-type(3) Selects the third input element
:first-of-type can be used for selecting first sibling of the candidates
:last-of-type can be used for selecting last sibling of the candidates
:only-of-type can be used for selecting an element that has no siblings with the same expanded element name.
Locating First Sibling
Following can be used for locating the first element from list of siblings.
Syntax:
CSS-of-Context-Element<space>Element:first-child
CSS-of-Context-Element>Element:first-child
Examples :
In following examples we select username input field distinctly from available three candidate elements.
- form>div>input:first-child
- form input:first-child
Locating Last Sibling
You can use :last-child to locate a last element from a list of siblings.
Syntax :
CSS-of-Parent-Element<space>Element>:last-child
CSS-of-Parent-Element>>Element>:last-child
Examples :
- form#frmLogin>input:last-child
- form#frmLogin>div:last-child
- form#frmLogin>*:last-child
Third input element will be selected in first example as shown in the figure. Last div element will be selected in second and third example.
Locating Siblings by their Position
You can use :nth-child(n) to locate an element from its first sibling and :nth-last-child(n) locate an element from the last sibling.
Syntax :
CSS-of-the-Siblings:nth-child(n)
CSS-of-the-Siblings:nth-last-child(n)
Examples :
- form#frmLogin>input:nth-child(3)
- form#frmLogin>*:nth-last-child(6)
Third input element will be selected in first and second examples as shown in the figure.
:only-child can be used for selecting elements with no siblings
:empty can be used for selecting elements without children
:only-of-type can be used for selecting elements with same element name
Locating Elements by prefix of attribute value
Following can be used when you have dynamic attribute values, but they begin with a fixed string.
Syntax :
tag-name[attribute-name^=’fixed-prefix-of-value’]
or [attribute-name^=’fixed-prefix-of-value’]
Examples :
- a[href^=’https://www.amazon.com/Magnasonic-‘]
- [href^=’https://www.amazon.com/Magnasonic-‘]
Locating Elements by suffix of attribute value
Following can be used when you know the dynamic attributes have fixed ending attribute value (suffix).
Syntax :
tag-name[attribute-name$=’fixed-suffix’
]
or [attribute-name$=’fixed-suffix’]
Example :
- input[name$=’name’]
- [name$=’name’]
Locating Elements by substring of attribute value
Following can be used when you know a substring of the attribute value is fixed.
Syntax :
tag-name[attribute-name*=’fixed-substring-of-the-value’]
Examples :
- a[href*=’Magnasonic-Professional‘]
- [href*=’Magnasonic-Professional‘]
Locating Elements by one word of the attribute value
Following can be used when your attribute value has more than one word separated by spaces.
Syntax :
tag-name[attribute-name~=’a white space separated value’]
Example :
- span[style~=’display:’]
[attribute-name|=’value’] can be used for locating element whose attribute value is exactly equal to value or attribute-value begin with value immediatelyfollowed by – (hyphen)
Locating next sibling with a known tag-name
Following can be used for locating immediate next sibling appear after a context element.
Syntax :
CSS-of-context-element
+
tag-name
CSS-of-context-element
+
*
Examples :
- [name=’actionID’] + input
- [name=’actionID’] + div
- [name=’actionID’] + *
Second input element will be selected in first example. No element will be selected in second example. Second input element will be selected in third example
Locating following sibling of a known element
Following syntax can be used for locating elements after the context element who has same patent. It will not select the descendants.
Syntax :
CSS-of-context-element ~ tag-name
CSS-of-context-element ~ *
Examples :
- [name=’actionID’] ~ input
- [name=’actionID’] ~ div
- [name=’actionID’] ~ *
Two input elements after the context element will be selected in first example. Five div elements will be selected in second example. All seven elements after the context element will be selected in the third example.
Locating element by part of the Inner Text
Following cannot be used for locating elements with their visible text available between opening and end tags. This is a limitation of CSS.
tag-name:contains(‘part-of-the-text’)
Use Xpath for locating elements by their innerText. You may use linkText or partialLinkText location strategies if the context element is an anchor tag <a>.
XPath Syntax :
Locating elements by attributes ignoring the case sensitivity
It is possible to locate the element ignoring the case sensitivity of the attribute values using the character i or I after the value.
Syntax :
tag-name[Attribute=’Value’ i]
[Attribute=’Value’ I]
Examples :
- [id=’txtusername‘ i ]
- [id=’txtUSERNAME‘ I ]
- input[id=’txtusername‘ i ]
Locating elements without specific attribute value
This will be useful when you need to ensure specific attribute value is not available in an element. The negation :not() can be used for selecting elements that are not represented by its arguments.
Syntax :
css-of-context-node:not([attribute2='value2'])
Example :
Let’s say you want to select all the input elements which are not hidden.
input:not([type=’hidden‘])
Locating selected /checked elements
Following can be used for locating selected (unselected) , checked radios, check boxes and options.
Syntax :
css-of-the-element:checked
css-of-the-element:not(:checked)
Examples :
Let’s say you want to select all the selected options and not selected.
option:checked
option:not(:checked)
Locating elements by multiple CSS selectors
You can evaluate two or more CSS selectors by separating them with a comma.
Syntax :
CSS-Selector1, CSS-Selector2, ... , CSS-SelectorN
Example :
Let’s say you need to select all input element with type text, password and submit.
[type=’text‘],[type=’password‘],[type=’submit‘]
Practicing CSS with a game
Now it’s time to practice CSS selectors. Lets use this fun game CSS Diner game.
In this demo, we show selecting the pickle on the fancy plate (Level 5 of 32) using CSS plate[id=’fancy’]>pickle
Validating CSS
It is important to ensure CSS used in your automation script is validated before running the script. Fixing the CSS errors after running the test is expensive. There are a number of tools available to validate the correctness of the XPaths.
- Google Chrome Developer Tools
- Ranorex Selocity
- ChroPath
Lets see how to use Chrome DevTools to validate CSS selectors.
- Navigate to the required page in Google chrome
- Right click on the page and Select Inspect
- Press Ctrl+F on Windows. Command + F on Mac
- Type the CSS to validate in the search box
- CSS is validated as you type
Auto-generating CSS
- Right click on the element
- Select Selector action from the context
- Select Copy CSS
Converting XPath into CSS
If you have decided use CSS and want to convert existing XPaths into CSS following program can be used. ccsify by Santiago Suarez Ordoñez
CSS Cheat Sheet
Category | CSS | Note |
---|---|---|
E[id=’i’] | Element |
|
[id=’i’] | Element(s) with id i | |
E[@name=’n’] | Element |
|
[@name=’n’] | Element(s) with name | |
E[A=’V’] | Element |
|
E[A*=’V’] | Element |
|
E[A^=’V’] | Element |
|
E[A$=’V’] | Element |
|
E1[A1=’V1’] , E2[A2=’V2’] | Element |
|
E[@A1=’V1’] , E[@A2=’V2’ ] | Element |
|
E:contains(’T’) | Element |
|
E:empty | Element |
|
E2~E1 | Element |
|
E2 + E1 | Element |
|
E:disabled | Element |
|
E:enabled | Element |
|
E:checked | Checkbox or radio element(s) |
Glossary
CSS | Cascading Style Sheets. CSS describes how HTML elements are displayed. |
CSS Selector | A CSS Selector is a combination of an element selector and a value which identifies the web element within a web page. They are string representations of HTML tags, attributes, Id and Class. |
DOM | Document Object Model. |
Attribute | All HTML elements can have attributes. Attributes provide additional information about an element. Attributes usually come in name/value pairs like: name="value" |
References
Css Vs. X Path. [ONLINE]
Available at: http://elementalselenium.com/tips/32-xpath-vs-css.
[Accessed 03 Feb 2020].
developer.mozilla.org : CSS Selectors | MDN Web Docs. [ONLINE]
Available at:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors.
[Accessed 10 Feb 2020].
jquery – CSS selector case insensitive for attributes – Stack Overflow. [ONLINE]
Available at:http://stackoverflow.com/questions/5671238/css-selector-case-insensitive-for-attributes.
[Accessed 03 Feb 2020].
Sauce Labs. 2016. Selenium Tips: CSS Selectors | Sauce Labs . [ONLINE]
Available at:https://saucelabs.com/resources/articles/selenium-tips-css-selectors.
[Accessed 03 Feb 2020].
Selenium Easy. 2016. CSS selectors for Selenium with example. [ONLINE]
Available at:https://www.seleniumeasy.com/selenium-tutorials/css-selectors-tutorial-for-selenium-with-examples.
[Accessed 03 Feb 2020].
W3C Recommendation 06 November 2018 [ONLINE]
Available at: https://www.w3.org/TR/css3-selectors/.
[Accessed 03 Feb 2020].
Saurabh Gupta. Quick Reference for Xpath and CSS locators – Selenium WebDriver. [ONLINE]
Available at: https://www.linkedin.com/pulse/quick-reference-xpath-css-locators-selenium-webdriver-saurabh-gupta.
[Accessed 02 Feb 2020].
Testing Excellence. CSS Selectors in Selenium WebDriver with Examples. [ONLINE]
Available at:http://www.testingexcellence.com/css-selectors-selenium-webdriver-tutorial/.
[Accessed 02 Feb 2020].
Comments
Ravi
Great post !! This is really helpful