Debunking CSS Selectors

Once you visit a nice website such as the Sauce Labs home page, you wonder how well the page has been designed, how good the colors look and how pleasing it to the eyes. Now if you have heard of HTML, you’ll think- Wow, this is something pretty good done with HTML. Sorry to break this out buddy- but this is not HTML alone. This pleasing design involves something else at play- which like a rainbow, colors everything, puts everything in order and makes this website and web-elements pleasing to the eyes of the visitors. Yes- ladies and gentlemen, it is your very own Cascading Style Sheets or CSS, as we like to call it. Without CSS, a plain HTML designed front end on Sauce Labs, will not look anything near to what it currently is.

This is what CSS does to a web front end UI-

html-css

 

The primary function of CSS is to provide a structured format for the HTML mark up tags beneath and also use the various colorful attributes it contains to provide an aesthetically pleasing experience to the user. Without CSS, a website would be very dull or boring.

CSS Selectors

But why are we talking about this beautification of website? We should be talking about catching and recognizing web elements and stuff right. Correct.

So when testing a web user interface, you need to recognize a web element and you don’t have an ID or a Name attribute for it, then what would you do? The first thing that comes to mind is – off-course, I’ll use an Xpath.

Good- but it can be messy and has limitations too. But what if I can use the power of the CSS and use it to recognize the web elements?  That would be pretty cool right. And also, since most of the browsers support CSS, it wouldn’t be a problem with the diverse range of browsers being used.

So, in Selenium, we have an option of using CSS Selectors. Selectors are nothing, but patterns that match against elements in a tree, and they form one of the various techniques to locate an element in an XML document. But how would I do that?

 

A CSS Selector is a combination of an element selector and a selector value which identifies the web element within a web page. Selector Pattern is made using HTML tags, attributes and their values.

css2bselectiors

 

Things to Consider

There are a few things to keep in mind when you’re about to learn or create a CSS Selector for your webdriver tests.

 

HTML  tag : An HTML tag is a markup tag that are like keywords for a browser. HTML tags in a web page helps to define the browser how it must format and display a content- which may be a web element like an input , or a button etc. HTML tags are useful because they are the base ,which helps us in recognizing a web element and type of a web element.

Attribute : An attribute defines a property for an web element,  and consists of an attribute/value pair, and appears within the opening tag. It is the attribute we want to use to create CSS Selector.

For example, ID for a web element can it an attribute, which has a value. Class is another attribute for a web element. We’ll use these attributes and their values while defining a CSS Selector.

 

Now, there are certain notations or mechanisms that we need to keep in mind while using certain attributes. There are two main things that we need to keep in mind –

  • For ID attribute, always use the hash (#), to pair it with the attribute value. It is mandatory to use the (#) sign to use for an ID attribute in CSS selector.
<input id="email" type="email" tabindex="1" name="email>
<div id="rsi_card" class="card signin-card>

The syntax for selecting id would be

[HTML_tag]#[Attribute_value]

 

which would translate the selector into

 


driver.find_element_by_css_selector("input#id='email'")

driver.find_element_by_css_selector("input[id='email']")

driver.find_element_by_css_selector("div#id='rsi_card'")

driver.find_element_by_css_selector("div[id='rsi_card']")

driver.find_element_by_css_selector("input#email")

driver.find_element_by_css_selector("div#rsi_card")

 

  • For Class attribute, always use the dot (.) , to pair it with an attribute value. For class or multiple classes, we use the dot (.) to combine the classes into a single CSS selector.
<input type="checkbox" class="uiInput">
 // For multiple classes
<input class="submit ipt second-ipt flex-table-ipt js-submit" type="email">

The syntax for selecting the class would be

[HTML_tag].[Value_of_attribute]

which makes the selector for the above HTML in this format


driver.find_element_by_css_selector("input.uiInput")

driver.find_element_by_css_selector("input.second-ipt")

driver.find_element_by_css_selector(".second-ipt")

driver.find_element_by_css_selector("ipt.second-ipt")

driver.find_element_by_css_selector("submit.second-ipt")

Using sub-strings in CSS Selectors

Not every time will you find static, non changing web elements in a web page. Many times, such dynamic web elements are associated with dynamic id’s and name’s which change with changing instances. Such web elements are difficult to address with normal CSS selectors, which uses static id’s and name’s and values. So in case of such web elements, we have an option of using a part of the attribute, so that we can match only that certain portion of the attribute value. We can achieve this using

  • (^) Halt character – use this to match a string using a prefix
  • ($) Dollar character- use this to match a string using a suffix
  • (*) Asterisk character – use this to match a string using a sub-string
  • (:) Colon  character – use this to match a string using contains method.

 

For example, we are having the following set of HTML mark ups in a web page

<div id="123_randomId">
<div id="randomId_456>
<div id="123_pattern_randomId">

So we can use the css selectors in matching these as


driver.find_element_by_css_selector("div[id^='123']")

driver.find_element_by_css_selector("div[id$='456']")

driver.find_element_by_css_selector("div[id*='_pattern_']")

driver.find_element_by_css_selector("div:contains('_pattern_')")

Locating Elements with Multiple Attributes

There are situation when you can’t use a single attribute value to select a web element. In such situations, we can use a combination of  attributes to find the web element like

<div class="ajax_enabled" style="display:block">

Here we can use both the class and style attribute to find the element


driver.find_element_by_css_selector("div[class='ajax_enabled'][style='display:block']")

Locating Child Elements

While using CSS selectors, direct child of a tree can be selected using a greater than sysmbol (>), which is equivalent to the slash(/), that we use in Xpath

//div/a

in CSS selector this would become

div>a

On the other hand, if an element is a sub-child of the root element (inside the child of the root), it can be selected by just using a whitespace – which is like double slash (//) in Xpath

//div//a

in CSS selector  this would become

div a

For example, see this example

<div id="child">
<img src="./logo.png">
</div>

Here we would select the image using this


driver.find_element_by_css_selector("div#child img")

There are occasions when there are multiple child elements within the same parent element such as list elements. For example

<ul id="fruit">
<li>Apple</li>
<li>Orange</li>
<li>Banana</li>
</ul>

As can be seen, these individual list elements don’t have any id or names associated with them. If we want to locate the element with text ‘Orange’, we have to use “nth-of-type” in this way


driver.find_element_by_css_selector("ul#fruit li:nth-of-type(2)")

We can also use the “last-child” to select the element with name “Banana


driver.find_element_by_css_selector("ul#fruit li:last-child")