info@pragmatictesters.com +94 11 253 8512

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 

Note: There are no selectors or combinators to select parent items, siblings of parents, or children of parent siblings.

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 

  1. Attribute values should be enclosed with single or double quotes 
  2. 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.classNameor
.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

Similarly
: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.

  1. form>div>input:first-child
  2. 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.

Similarly
: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:]

Note :

[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 :

//elemnet-name[text()=’exact-innerText‘]
//elemnet-name[contains(text(),’part-of-innerText‘]

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=Valuei]
[Attribute=ValueI]

Examples :

  • [id=’txtusername i ]
  • [id=’txtUSERNAMEI ]
  • input[id=’txtusernamei ]

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.

  1. Google Chrome Developer Tools 
  2. Ranorex Selocity 
  3. ChroPath

Lets see how to use Chrome DevTools to validate CSS selectors.

  1. Navigate to the required page in Google chrome 
  2. Right click on the page and Select Inspect 
  3. Press Ctrl+F on Windows. Command + F on Mac
  4. Type the CSS to validate in the search box 
  5. 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

CategoryCSSNote
E[id=’i’]Element with id i
[id=’i’]Element(s) with id i
E[@name=’n’]Element with name n
[@name=’n’]Element(s) with name
E[A=’V’]Element with attribute A containing value exactly V
E[A*=’V’]Element with attribute A containing value V
E[A^=’V’]Element with attribute A starting with value V
E[A$=’V’]Element with attribute A ending with value V
E1[A1=’V1’] , E2[A2=’V2’]Element with attribute A1 and value V1 or Element with attribute A2 and value V2
E[@A1=’V1’] , E[@A2=’V2’ ]Element with attribute A1 and value V1 or attribute A2 and value V2
E:contains(’T’)Element with inner text T
E:emptyElement with no child elements
E2~E1Element following some sibling(s) of element
E2 + E1Element following immediately element of type
E:disabledElement that is disabled
E:enabledElement that is not disabled
E:checkedCheckbox or radio element(s) checked

Glossary

CSSCascading Style Sheets. CSS describes how HTML elements are displayed.
CSS SelectorA 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.
DOMDocument Object Model.
AttributeAll 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].

Author: Janesh Kodikara

Performance Tester | JMeter Trainer | Software Testing Service Provider

Your Turn To Talk

Leave a reply:

Your email address will not be published.