CSS to XPath Conversion

CSS and XPath are both useful syntaxes for targeting elements within a webpage’s DOM. In the case of Ghost Inspector, both are supported for targeting elements within your test steps. By default, Ghost Inspector assumes that you are targeting elements using CSS and that's the syntax used by our test recorder. For XPath targeting, simply prefix the step’s target with xpath= in the test editor.

While their syntax differs, CSS and XPath offer similar methods for targeting elements and so conversion is often easy. Below are some simple tables that can be used for converting between the two syntaxes.

Table of Contents

Targeting using Element Tags

Any element*//*
Any <p> elementp//p
Any <div> elementdiv//div

Targeting using Attributes

Any <button> where name equals sendbutton[name="send"]//button[@name="send"]
Any element where type equals submit[type="submit"]//*[@type="submit"]
Any element where href begins with abc[href^="abc"]//*[starts-with(@href, "abc")]
Any element where href ends with xyz[href$="abc"]//*[ends-with(@href, "abc")]
Any element where href contains mno[href*="mno"]//*[contains(@href, "abc")]

Targeting using IDs

CSS has a shorthand syntax that can be used when matching by ID. XPath uses it’s standard attribute syntax, since and ID is simply a normal attribute.

Any element where id equals sample#sample//*[@id="sample"]

Targeting using Classes

As with IDs, CSS has a shorthand syntax for matching via classes.

Any element where class includes highlight.highlight//*[contains(concat(" ", @class, " "), " highlight ")]

You might be wondering “What's with the concat and spaces in the XPath version? Why can't we just use //*[contains(@class, "highlight")]” The danger there is that, in addition to matching highlight, the XPath would also match a class like highlightDark. It would just be looking for the text highlight in the class attribute and not considering whether it's a distinct class name. By checking for spacing around the string, we ensure it's distinct. You can opt for the shorter syntax if that's not a concern.

Targeting using Contents

Any h1 element with the exact text Dashboard//h1[text()="Dashboard"]
Any h1 element containing text Dashboardh1:contains("Dashboard")//h1[contains(text(), "Dashboard")]

The :contains() feature is not standard CSS. It’s an addition provided by the Sizzle selector engine (popularized by jQuery). Unfortunately, it’s not available in most CSS contexts. For Ghost Inspector usage, we recommend using XPath to match elements by contents.

Targeting using Hierarchy

Leveraging hierarchy allows us to match descendent elements that are nested inside of other elements. Here's some sample HTML to help clarify the difference between a “child” and a “descendent”.

<div id="sample">
  <span>This is both a child and descendent of #sample.</span>
  <div class="nested">
    <span>This is a descendent of #sample only.</span>
Any <span> element that’s a “direct” child of #sample#sample > span//*[@id="sample"]/span
Any <span> element that’s a descendent of #sample#sample span//*[@id="sample"]//span

Additional Targeting Options

The 3rd <li> element in a listli:nth-of-type(3)//li[3]