CSS Selectors
Master CSS selectors for finding elements in Selenium. Learn syntax, best practices, and common patterns.
Selenium 3 & 4 Stable
CSS selectors are the recommended way to locate elements in Selenium. They’re faster than XPath, more readable, and widely understood by web developers.
Basic Selectors
By ID
Select by ID
Selenium 3 & 4 Stable
// Using CSS selectorWebElement element = driver.findElement(By.cssSelector("#username"));
// Equivalent using By.idWebElement element = driver.findElement(By.id("username"));# Using CSS selectorelement = driver.find_element(By.CSS_SELECTOR, "#username")
# Equivalent using By.IDelement = driver.find_element(By.ID, "username")// Using CSS selectorconst element = await driver.findElement(By.css('#username'));
// Equivalent using By.idconst element = await driver.findElement(By.id('username'));// Using CSS selectorIWebElement element = driver.FindElement(By.CssSelector("#username"));
// Equivalent using By.IdIWebElement element = driver.FindElement(By.Id("username"));By Class
Select by Class
Selenium 3 & 4 Stable
// Single classWebElement element = driver.findElement(By.cssSelector(".btn-primary"));
// Multiple classes (element has both classes)WebElement element = driver.findElement(By.cssSelector(".btn.btn-primary"));# Single classelement = driver.find_element(By.CSS_SELECTOR, ".btn-primary")
# Multiple classes (element has both classes)element = driver.find_element(By.CSS_SELECTOR, ".btn.btn-primary")// Single classconst element = await driver.findElement(By.css('.btn-primary'));
// Multiple classes (element has both classes)const element = await driver.findElement(By.css('.btn.btn-primary'));// Single classIWebElement element = driver.FindElement(By.CssSelector(".btn-primary"));
// Multiple classes (element has both classes)IWebElement element = driver.FindElement(By.CssSelector(".btn.btn-primary"));By Tag Name
Select by Tag
Selenium 3 & 4 Stable
// All buttonsList<WebElement> buttons = driver.findElements(By.cssSelector("button"));
// All inputs of type textList<WebElement> textInputs = driver.findElements(By.cssSelector("input[type='text']"));# All buttonsbuttons = driver.find_elements(By.CSS_SELECTOR, "button")
# All inputs of type texttext_inputs = driver.find_elements(By.CSS_SELECTOR, "input[type='text']")// All buttonsconst buttons = await driver.findElements(By.css('button'));
// All inputs of type textconst textInputs = await driver.findElements(By.css("input[type='text']"));// All buttonsIList<IWebElement> buttons = driver.FindElements(By.CssSelector("button"));
// All inputs of type textIList<IWebElement> textInputs = driver.FindElements(By.CssSelector("input[type='text']"));Attribute Selectors
| Selector | Description |
|---|---|
[attr] | Has attribute |
[attr='value'] | Exact match |
[attr^='value'] | Starts with |
[attr$='value'] | Ends with |
[attr*='value'] | Contains |
Attribute Selectors
Selenium 3 & 4 Stable
// Has attributedriver.findElement(By.cssSelector("[data-testid]"));
// Exact matchdriver.findElement(By.cssSelector("[data-testid='submit-btn']"));
// Starts withdriver.findElement(By.cssSelector("[id^='user_']"));
// Ends withdriver.findElement(By.cssSelector("[id$='_input']"));
// Containsdriver.findElement(By.cssSelector("[class*='primary']"));# Has attributedriver.find_element(By.CSS_SELECTOR, "[data-testid]")
# Exact matchdriver.find_element(By.CSS_SELECTOR, "[data-testid='submit-btn']")
# Starts withdriver.find_element(By.CSS_SELECTOR, "[id^='user_']")
# Ends withdriver.find_element(By.CSS_SELECTOR, "[id$='_input']")
# Containsdriver.find_element(By.CSS_SELECTOR, "[class*='primary']")// Has attributeawait driver.findElement(By.css('[data-testid]'));
// Exact matchawait driver.findElement(By.css("[data-testid='submit-btn']"));
// Starts withawait driver.findElement(By.css("[id^='user_']"));
// Ends withawait driver.findElement(By.css("[id$='_input']"));
// Containsawait driver.findElement(By.css("[class*='primary']"));// Has attributedriver.FindElement(By.CssSelector("[data-testid]"));
// Exact matchdriver.FindElement(By.CssSelector("[data-testid='submit-btn']"));
// Starts withdriver.FindElement(By.CssSelector("[id^='user_']"));
// Ends withdriver.FindElement(By.CssSelector("[id$='_input']"));
// Containsdriver.FindElement(By.CssSelector("[class*='primary']"));Combinators
Descendant (space)
Selects all descendants:
div.container p /* All <p> inside div.container */Child (>)
Selects only direct children:
ul > li /* Direct <li> children of <ul> */Adjacent Sibling (+)
Selects the immediate next sibling:
h2 + p /* <p> immediately after <h2> */General Sibling (~)
Selects all following siblings:
h2 ~ p /* All <p> after <h2> at same level */ Combinator Examples
Selenium 3 & 4 Stable
// Descendant - any depthdriver.findElement(By.cssSelector("form input"));
// Direct child onlydriver.findElement(By.cssSelector("ul > li"));
// Adjacent siblingdriver.findElement(By.cssSelector("label + input"));
// General siblingdriver.findElements(By.cssSelector("h2 ~ p"));# Descendant - any depthdriver.find_element(By.CSS_SELECTOR, "form input")
# Direct child onlydriver.find_element(By.CSS_SELECTOR, "ul > li")
# Adjacent siblingdriver.find_element(By.CSS_SELECTOR, "label + input")
# General siblingdriver.find_elements(By.CSS_SELECTOR, "h2 ~ p")// Descendant - any depthawait driver.findElement(By.css('form input'));
// Direct child onlyawait driver.findElement(By.css('ul > li'));
// Adjacent siblingawait driver.findElement(By.css('label + input'));
// General siblingawait driver.findElements(By.css('h2 ~ p'));// Descendant - any depthdriver.FindElement(By.CssSelector("form input"));
// Direct child onlydriver.FindElement(By.CssSelector("ul > li"));
// Adjacent siblingdriver.FindElement(By.CssSelector("label + input"));
// General siblingdriver.FindElements(By.CssSelector("h2 ~ p"));Pseudo-Selectors
nth-child
Position-Based Selection
Selenium 3 & 4 Medium
// First itemdriver.findElement(By.cssSelector("ul li:first-child"));
// Last itemdriver.findElement(By.cssSelector("ul li:last-child"));
// Second item (1-indexed)driver.findElement(By.cssSelector("ul li:nth-child(2)"));
// Every odd itemdriver.findElements(By.cssSelector("tr:nth-child(odd)"));
// Every 3rd itemdriver.findElements(By.cssSelector("li:nth-child(3n)"));# First itemdriver.find_element(By.CSS_SELECTOR, "ul li:first-child")
# Last itemdriver.find_element(By.CSS_SELECTOR, "ul li:last-child")
# Second item (1-indexed)driver.find_element(By.CSS_SELECTOR, "ul li:nth-child(2)")
# Every odd itemdriver.find_elements(By.CSS_SELECTOR, "tr:nth-child(odd)")
# Every 3rd itemdriver.find_elements(By.CSS_SELECTOR, "li:nth-child(3n)")// First itemawait driver.findElement(By.css('ul li:first-child'));
// Last itemawait driver.findElement(By.css('ul li:last-child'));
// Second item (1-indexed)await driver.findElement(By.css('ul li:nth-child(2)'));
// Every odd itemawait driver.findElements(By.css('tr:nth-child(odd)'));
// Every 3rd itemawait driver.findElements(By.css('li:nth-child(3n)'));// First itemdriver.FindElement(By.CssSelector("ul li:first-child"));
// Last itemdriver.FindElement(By.CssSelector("ul li:last-child"));
// Second item (1-indexed)driver.FindElement(By.CssSelector("ul li:nth-child(2)"));
// Every odd itemdriver.FindElements(By.CssSelector("tr:nth-child(odd)"));
// Every 3rd itemdriver.FindElements(By.CssSelector("li:nth-child(3n)"));CSS vs XPath
| Feature | CSS | XPath |
|---|---|---|
| Speed | Faster | Slower |
| Readability | More intuitive | Can be complex |
| Text content | Cannot select by text | Can select by text |
| Axes | Limited (descendants, siblings) | Full (parent, ancestor, etc.) |
| Browser support | Excellent | Excellent |
Recommendation: Use CSS selectors as your default. Switch to XPath only when you need features CSS doesn’t support (like selecting by text or navigating to parent elements).
Want to master XPath selectors? Visit XPath Decoded
Best Practices
- Prefer IDs over classes:
#submit-btnis more stable than.btn-primary - Use data attributes:
[data-testid='login-form']is designed for testing - Keep selectors short: Avoid deeply nested selectors
- Avoid indexes when possible:
:nth-child(2)breaks if order changes - Test selectors in DevTools: Use
$$('selector')in browser console
Next Steps
- XPath Basics - When CSS isn’t enough
- XPath Advanced - Complex XPath patterns
- Relative Locators - Selenium 4 spatial locators
- Explicit Waits - Wait for elements to appear