Selenium Tips: CSS Selectors in Selenium Demystified

January 29th, 2010 by Santiago Suarez Ordoñez

Following my previous Selenium testing TOTW about improving your locators, this blog post will show you some advanced CSS rules and pseudo-classes that will help you move your XPATH locators to CSS, a native approach on all browsers.

Next sibling

Our first example is useful for navigating lists of elements, such as forms or ul items. The next sibling will tell selenium to find the next adjacent element on the page that’s inside the same parent. Let’s show an example using a form to select the field after username.

</input> </input>

Let’s write a css selector that will choose the input field after “username”. This will select the “alias” input, or will select a different element if the form is reordered.

css=form input.username + input

Attribute values

If you don’t care about the ordering of child elements, you can use an attribute selector in selenium to choose elements based on any attribute value. A good example would be choosing the ‘username’ element of the form without adding a class.

</input> </input> </input> </input>

We can easily select the username element without adding a class or an id to the element.

css=form input[name='username']

We can even chain filters to be more specific with our selections.

css=input[name='continue'][type='button']

Here Selenium will act on the input field with name=”continue” and type=”button”

Choosing a specific match

CSS selectors in Selenium allow us to navigate lists with more finess that the above methods. If we have a ul and we want to select its fourth li element without regard to any other elements, we should use nth-child or nth-of-type.

    <p>Heading</p>

  • Cat
  • Dog
  • Car
  • Goat

If we want to select the fourth li element (Goat) in this list, we can use the nth-of-type, which will find the fourth li in the list.

css=ul#recordlist li:nth-of-type(4)

On the other hand, if we want to get the fourth element only if it is a li element, we can use a filtered nth-child which will select (Car) in this case.

css=ul#recordlist li:nth-child(4)

Note, if you don’t specify a child type for nth-child it will allow you to select the fourth child without regard to type. This may be useful in testing css layout in selenium.

css=ul#recordlist *:nth-child(4)

Sub-string matches

CSS in Selenium has an interesting feature of allowing partial string matches using ^=, $=, or *=. I’ll define them, then show an example of each:

^= Match a prefix
$= Match a suffix
*= Match a substring
css=a[id^='id_prefix_']

A link with an “id” that starts with the text “id_prefix_”

css=a[id$='_id_sufix']

A link with an “id” that ends with the text “_id_sufix”

css=a[id*='id_pattern']

A link with an “id” that contains the text “id_pattern”

Matching by inner text

And last, one of the more useful pseudo-classes, :contains() will match elements with the desired text block:

css=a:contains('Log Out')

This will find the log out button on your page no matter where it’s located. This is by far my favorite CSS selector and I find it greatly simplifies a lot of my test code.

Tune in next week for more Selenium testing tips from Sauce Labs.

Sauce Labs is the leading cloud testing platform that allows you to test across 170+ browsers/OS platforms in the cloud. With Selenium IDE and Selenium RC compatibilities, you can get complete cross-platform browser testing today.

Comments (You may use the <code> or <pre> tags in your comment)

  1. TK says:

    Hey,

    thank you very much. This is awesome.

    Stay tuned. TK

  2. Hello! Wonderful concept, but will this really perform?

    Robert

  3. Well, the best answer is that it really depends on each test and situation. But if your test requirements involve IE, it’s definitely worth a try.

  4. TK says:

    @Hydrolyze

    It is more than a try.
    I’ve implemented these tips and I am impressed.

    My testduration was with Xpath and IE (6,7,8) more than five minutes.
    Now with the css locator instead of the Xpath the test duration is not more than a minute.

    Conclusion: It will really perform. Just try it. You’ll be impressed.

    TK

  5. JP says:

    Is there a pseudo-classes selector to match exact inner text? Or another strategy?

    JP

  6. @JP:

    Yeah, for finding elements depending on their inner text, you can use the following CSS pseudo class:

    css=a:contains(“Inner Text”)

  7. [...] we already mentioned in our previous posts CSS Selectors in Selenium Demystified and Start improving your locators, CSS as a location strategy generally far outperforms [...]

  8. uday says:

    when i try to select nth element in a list of elements of same type using nth-type-of as shown in ur exmaple, its not working.

    i wish it is not supported by selenium.Source
    http://release.seleniumhq.org/selenium-core/1.0.1/reference.html

    “Currently the css selector locator supports all css1, css2 and css3 selectors except namespace in css3, some pseudo classes(:nth-of-type, :nth-last-of-type, :first-of-type, :last-of-type, :only-of-type, :visited, :hover, :active, :focus, :indeterminate) and pseudo elements(::first-line, ::first-letter, ::selection, ::before, ::after)”.

  9. Alex S says:

    Guys, thanks for very useful post,
    and I wonder what do you think how do we replace the XPATH: preceding-sibling
    with CSS?
    can someone give an example,
    using the code from “Next sibling” in this article:

    How to find the previous element if I know only the input “alias” element.

    Thanks!

  10. Arun says:

    Is there a pseudo-classes selector to match exact inner text?

    we can use a:contains(Text1) but if the element ‘a’ contains TempText1 as its text also will match

  11. strawberry says:

    Hi,

    For the following case,how to use the css selector?

    cat
    tiger

    As there is a space between “mini” and “shared”,I try as following but all failure.
    css=ul.mini shared li:nth-child(1)
    css=ul.(mini shared) li:nth-child(1)
    css=ul.[mini shared] li:nth-child(1)

    Any idea?

    Thanks!

  12. Alex says:

    2 strawberry:

    You need to use the following syntax:
    css=ul[class='mini'] shared li:nth-child(1)

    Same situation with id, for example:
    css=form#myId => css=form[id='myId']

  13. Alex says:

    2 strawberry again:

    Sorry for the misprint, I meant
    css=ul[class='mini shared'] li:nth-child(1)
    of course.
    It seems for me it’s time to go to sleep :)

  14. kevin says:

    regarding:
    css=ul#recordlist li:nth-of-type(4)

    I thought nth-of-type was not a supported pseudo class of selenium? I haven’t been able to get this to work.

  15. strawberry says:

    Thanks Alex! It works now!

  16. Josh says:

    I’ve had the same experience as @kevin.

    The :nth-of-type() pseudo-class doesn’t appear to be supported… so I’m confused as to why Sauce would be recommending it.

    Hey @Santiago… care to comment?
    I’d love to use this advice, but after trying it out in my tests, I got a bunch of failures. (See @uday’s comment above.)

    What works in FireFinder/Firebug doesn’t always work in Selenium.

  17. David says:

    In my web page I have to occurrences of a row e.g.

    14

    18

    I can refer to the first occurrence using:
    selenium.GetText(“css=tr.tablerow_on td:nth-child(1)”)

    How do I refer to the second occurrence e.g the td valued 18?

  18. Looks like your code was escaped, try wrapping it within <code> tags.
    Just guessing what your code is, I’d say it should be done using something like:
    css=tr.tablerow_on td:nth-child(2)

    Did you try that?

  19. Steve says:

    What about matching an input with a prefix and a suffix. Say I had an input with ID prefix_somerandomsequence_suffix?

    obviously css=input[id^='prefix_' id$='_suffix'] does not work but is there something similar?

  20. Couldn’t try it yet, but I’d write it like the following:
    css=input[id^='prefix_'][id$='_suffix']

    Let us know if it works.

  21. tester :) says:

    hi,

    I am using selenium 1.0.1 and it does not seem to support nth-type.

    I am using Java to write my tests.

    Which version and coding language are you guys using

    Thanks
    Nidhi

  22. ChaotX says:

    I’d like to mention that regarding the :nth-* pseudo-classes IE(before 9 beta) have a lack of compatibility. Maybe that’s why not worth to use them, if multi browser testing is important.

    http://msdn.microsoft.com/en-us/library/cc351024(VS.85).aspx

  23. ndk says:

    contains in CSS selectors does not work in Selenium 2.0. For example,

    By.xpath(“.//div[contains(text(), 'foo')]“)
    I want to replace this with
    By.cssSelector(“div:contains(‘foo’)”).
    However this is not working. I learnt that contains is deprecated from css3. Any workaround guys?

  24. bl says:

    How do you get Selenium to click on one of these though? We have a widget on our page that dynamically generates part of its xpath/css location (the part after the ‘_’ below) each time the page is loaded – and while I can ask selenium if an element that starts with the static portion of the element exists, I can’t get selenium to click on the element based on the static match – the line executes without an error but the widget is not invoked on the web page. Without being able to control the widget, how can you get selenium to act on the button? Any help is greatly appreciated.

    xpath example:
    storeElementPresent | //div[contains(@id,'connect_widget_')] | widgetbtn

    css example :
    storeElementPresent | css=div[id^='connect_widget_'] | widgetbtn

  25. Just published on Simple-Talk.com, my article “XPath, CSS, DOM and Selenium: The Rosetta Stone” may be of interest to readers of this blog. It presents a wallchart/cross-reference providing a large collection of recipes in all four technologies, showing you instantly how to map from one to another. It also shows Selenium idiosyncracies with respect to the actual standards for each technology in copious footnotes. I could not find anything even close to this, which inspired me to create it myself. Here’s the link: http://www.simple-talk.com/dotnet/.net-framework/xpath,-css,-dom-and-selenium-the-rosetta-stone/

  26. Simounet says:

    @bl : You can use the clickAt command, it will open your menu and make includes items available.

    Thanks for this very useful article by the way.

  27. Mark Heilman says:

    Am trying to find the 5th checkbox, ie. there are initially 4 on page display and when check one the jobs will post with another check box. Being this is a GWT developed web app, don’t want to rely upon GWT tag ids, etc… as they are dynamic. Using DOM, or Xpath is bleak as not much available, and CSS looks like my only hope for IE.
    Thanks
    Mark

  28. Santosh says:

    Hi

    I want to use regular expression for class
    css=select.myclassnamepattern*

    Is there a way to do this?
    My class name should be a regular expression pattern

  29. Santosh says:

    one more thing … How to handle if a class name has a space

  30. Santosh says:

    My class name is like this “xyz abc”
    it means 2 classes i guess
    so i used xyz.abc
    it doesn’t work

  31. skundam says:

    How to click a button if the css is “css=a.rtsLink.rtsClicked > span.rtsOut > span.rtsIn > span.rtsTxt”?.

  32. Ramesh says:

    Ok

    how to identify span with text “OK”

  33. enhanceqa says:

    how to identify span with text “OK” which is enclosed between span tag with css
    “Ok”

  34. Ny says:

    Hello,
    I am so new to Selenium.
    I think i will focus on css locator but I find on selenium document, it is not too much. When i read CSS topic on w3s, it is not the same to selenium…Im so confused. I dont know where to start…
    Can any one help to show me the way?

    Thanks to much
    Ny

  35. Tina says:

    I am new to use selenium.
    It’s very helpful to me.

    Thanks,
    Tina

  36. Sebastien says:

    Hello

    Anyone know of a Firefox pluggin I could use to test CSS selectors before I put them in my code?

    For xpath, I use xpather which allows me to type all my fancy xpaths and shows me the matches, or right click anywhere on the page to get the xpath of the element.
    That helps me cut on development time which, at least in my manager’s opinion, is even more important than cutting a few seconds of execution time. But of course, if I can get the best of both worlds, I would be more than happy…

    Also, are css locators prone to cross-browser issues? One thing I like about xpaths is that they are pretty consistent across browsers expect for some features like selecting by index.

  37. David says:

    FYI:

    This article is great, but needs to point out that not all the CSS selectors like “tag:contains(‘text’)” will work under Selenium 2 / WebDriver. That is because :contains is one of the pseudo-classes that isn’t part of standard CSS but usable with CSS libraries like Sizzle. Selenium 1/RC used Sizzle for CSS across all browsers. In Selenium 2, it is only used where necessary like IE and other browsers use the native standard CSS (w/o the extra features).

    So if you still want :contains going in Selenium 2, you’ll need to inject Sizzle library into the web page and do lookup with that.

    And for testing CSS locators prior to putting in Selenium, I use Firebug addon called FirePath. It lets you test XPath, standard CSS, and Sizzle-based CSS.

  38. Sebastien says:

    Thanks for the FirePath tip David. That works great!

  39. likeapple says:

    My structure html is:

    Home

    <!–[if lt IE 8]><![endif]–>

    Roles

    <!–[if lt IE 8]><![endif]–>

    Group Accounts

    <!–[if lt IE 8]><![endif]–>

    User Accounts
    I want to click into Group Account, How do I write by selenium?

    I wrote that:
    WebElement element = driver.findElement(By.cssSelector(“css=ul#navigation li:nth-of-type(4)a span”));
    But it doen’t work?
    Please help me. Thank in advance
    But

  40. likeapple says:

    Sorry because it has been error when I post html code:
    My structure html is:
    1.
    2.
    3. Home
    4.
    5.
    6
    7.
    8. Roles
    9.
    10.
    11.
    12 Group Accounts
    13.
    14.
    15.

  41. [...] you ready to use CSS with selenium? 2. Multiple classes and ID’s, CSS- trips and tricks. 3. CSS selectors demystified from Sauceio  4. Multiple classes and CSS by Maxdesign 5. Can I use this ?  Search 6. Css Rosetta stone [...]

Leave a Comment