Relative Locators
Use Selenium 4's relative locators to find elements based on their visual position relative to other elements.
Selenium 4 Medium
Selenium 4 introduced relative locators (also called “friendly locators”) that let you find elements based on their visual position relative to other elements on the page.
Available Relative Locators
| Locator | Description |
|---|---|
above() | Element above the reference |
below() | Element below the reference |
toLeftOf() | Element to the left of reference |
toRightOf() | Element to the right of reference |
near() | Element within ~50px of reference |
Basic Usage
Relative Locators Basics
Selenium 4 Medium
import org.openqa.selenium.By;import org.openqa.selenium.WebElement;import static org.openqa.selenium.support.locators.RelativeLocator.with;
// Find the reference element firstWebElement emailLabel = driver.findElement(By.id("email-label"));
// Find input below the email labelWebElement emailInput = driver.findElement( with(By.tagName("input")).below(emailLabel));
// Find button to the right of cancel buttonWebElement cancelBtn = driver.findElement(By.id("cancel"));WebElement submitBtn = driver.findElement( with(By.tagName("button")).toRightOf(cancelBtn));
// Find label above an input fieldWebElement passwordInput = driver.findElement(By.id("password"));WebElement passwordLabel = driver.findElement( with(By.tagName("label")).above(passwordInput));
// Find element to the leftWebElement priceValue = driver.findElement(By.className("price"));WebElement priceLabel = driver.findElement( with(By.tagName("span")).toLeftOf(priceValue));from selenium.webdriver.common.by import Byfrom selenium.webdriver.support.relative_locator import locate_with
# Find the reference element firstemail_label = driver.find_element(By.ID, "email-label")
# Find input below the email labelemail_input = driver.find_element( locate_with(By.TAG_NAME, "input").below(email_label))
# Find button to the right of cancel buttoncancel_btn = driver.find_element(By.ID, "cancel")submit_btn = driver.find_element( locate_with(By.TAG_NAME, "button").to_right_of(cancel_btn))
# Find label above an input fieldpassword_input = driver.find_element(By.ID, "password")password_label = driver.find_element( locate_with(By.TAG_NAME, "label").above(password_input))
# Find element to the leftprice_value = driver.find_element(By.CLASS_NAME, "price")price_label = driver.find_element( locate_with(By.TAG_NAME, "span").to_left_of(price_value))const { By, locateWith } = require('selenium-webdriver');
// Find the reference element firstconst emailLabel = await driver.findElement(By.id('email-label'));
// Find input below the email labelconst emailInput = await driver.findElement( locateWith(By.tagName('input')).below(emailLabel));
// Find button to the right of cancel buttonconst cancelBtn = await driver.findElement(By.id('cancel'));const submitBtn = await driver.findElement( locateWith(By.tagName('button')).toRightOf(cancelBtn));
// Find label above an input fieldconst passwordInput = await driver.findElement(By.id('password'));const passwordLabel = await driver.findElement( locateWith(By.tagName('label')).above(passwordInput));
// Find element to the leftconst priceValue = await driver.findElement(By.className('price'));const priceLabel = await driver.findElement( locateWith(By.tagName('span')).toLeftOf(priceValue));using OpenQA.Selenium;using static OpenQA.Selenium.RelativeBy;
// Find the reference element firstIWebElement emailLabel = driver.FindElement(By.Id("email-label"));
// Find input below the email labelIWebElement emailInput = driver.FindElement( RelativeBy.WithLocator(By.TagName("input")).Below(emailLabel));
// Find button to the right of cancel buttonIWebElement cancelBtn = driver.FindElement(By.Id("cancel"));IWebElement submitBtn = driver.FindElement( RelativeBy.WithLocator(By.TagName("button")).RightOf(cancelBtn));
// Find label above an input fieldIWebElement passwordInput = driver.FindElement(By.Id("password"));IWebElement passwordLabel = driver.FindElement( RelativeBy.WithLocator(By.TagName("label")).Above(passwordInput));
// Find element to the leftIWebElement priceValue = driver.FindElement(By.ClassName("price"));IWebElement priceLabel = driver.FindElement( RelativeBy.WithLocator(By.TagName("span")).LeftOf(priceValue));The near() Locator
The near() locator finds elements within approximately 50 pixels of the reference:
Using near() Locator
Selenium 4 Medium
// Find icon near a labelWebElement label = driver.findElement(By.id("status-label"));WebElement icon = driver.findElement( with(By.className("icon")).near(label));
// Specify custom distance (in pixels)WebElement nearbyElement = driver.findElement( with(By.tagName("span")).near(label, 100));# Find icon near a labellabel = driver.find_element(By.ID, "status-label")icon = driver.find_element( locate_with(By.CLASS_NAME, "icon").near(label))
# Specify custom distance (in pixels)nearby_element = driver.find_element( locate_with(By.TAG_NAME, "span").near(label, 100))// Find icon near a labelconst label = await driver.findElement(By.id('status-label'));const icon = await driver.findElement( locateWith(By.className('icon')).near(label));
// Specify custom distance (in pixels)const nearbyElement = await driver.findElement( locateWith(By.tagName('span')).near(label, 100));// Find icon near a labelIWebElement label = driver.FindElement(By.Id("status-label"));IWebElement icon = driver.FindElement( RelativeBy.WithLocator(By.ClassName("icon")).Near(label));
// Specify custom distance (in pixels)IWebElement nearbyElement = driver.FindElement( RelativeBy.WithLocator(By.TagName("span")).Near(label, 100));Chaining Relative Locators
Combine multiple relative locators for precise element location:
Chaining Relative Locators
Selenium 4 Medium
// Find element that is both below one element AND to the right of anotherWebElement header = driver.findElement(By.id("section-header"));WebElement sidebar = driver.findElement(By.id("sidebar"));
WebElement content = driver.findElement( with(By.className("content")) .below(header) .toRightOf(sidebar));
// Find button below a label and to the right of cancelWebElement nameLabel = driver.findElement(By.id("name-label"));WebElement cancelBtn = driver.findElement(By.id("cancel"));
WebElement submitBtn = driver.findElement( with(By.tagName("button")) .below(nameLabel) .toRightOf(cancelBtn));# Find element that is both below one element AND to the right of anotherheader = driver.find_element(By.ID, "section-header")sidebar = driver.find_element(By.ID, "sidebar")
content = driver.find_element( locate_with(By.CLASS_NAME, "content") .below(header) .to_right_of(sidebar))
# Find button below a label and to the right of cancelname_label = driver.find_element(By.ID, "name-label")cancel_btn = driver.find_element(By.ID, "cancel")
submit_btn = driver.find_element( locate_with(By.TAG_NAME, "button") .below(name_label) .to_right_of(cancel_btn))// Find element that is both below one element AND to the right of anotherconst header = await driver.findElement(By.id('section-header'));const sidebar = await driver.findElement(By.id('sidebar'));
const content = await driver.findElement( locateWith(By.className('content')) .below(header) .toRightOf(sidebar));
// Find button below a label and to the right of cancelconst nameLabel = await driver.findElement(By.id('name-label'));const cancelBtn = await driver.findElement(By.id('cancel'));
const submitBtn = await driver.findElement( locateWith(By.tagName('button')) .below(nameLabel) .toRightOf(cancelBtn));// Find element that is both below one element AND to the right of anotherIWebElement header = driver.FindElement(By.Id("section-header"));IWebElement sidebar = driver.FindElement(By.Id("sidebar"));
IWebElement content = driver.FindElement( RelativeBy.WithLocator(By.ClassName("content")) .Below(header) .RightOf(sidebar));
// Find button below a label and to the right of cancelIWebElement nameLabel = driver.FindElement(By.Id("name-label"));IWebElement cancelBtn = driver.FindElement(By.Id("cancel"));
IWebElement submitBtn = driver.FindElement( RelativeBy.WithLocator(By.TagName("button")) .Below(nameLabel) .RightOf(cancelBtn));Practical Examples
Form Field Navigation
Form Field Location
Selenium 4 Medium
// Find input field associated with a labelWebElement firstNameLabel = driver.findElement( By.xpath("//label[text()='First Name']"));WebElement firstNameInput = driver.findElement( with(By.tagName("input")).toRightOf(firstNameLabel));// Or below for vertical form layoutsWebElement verticalInput = driver.findElement( with(By.tagName("input")).below(firstNameLabel));
// Find error message below an inputWebElement emailInput = driver.findElement(By.id("email"));WebElement errorMessage = driver.findElement( with(By.className("error")).below(emailInput));# Find input field associated with a labelfirst_name_label = driver.find_element( By.XPATH, "//label[text()='First Name']")first_name_input = driver.find_element( locate_with(By.TAG_NAME, "input").to_right_of(first_name_label))# Or below for vertical form layoutsvertical_input = driver.find_element( locate_with(By.TAG_NAME, "input").below(first_name_label))
# Find error message below an inputemail_input = driver.find_element(By.ID, "email")error_message = driver.find_element( locate_with(By.CLASS_NAME, "error").below(email_input))// Find input field associated with a labelconst firstNameLabel = await driver.findElement( By.xpath("//label[text()='First Name']"));const firstNameInput = await driver.findElement( locateWith(By.tagName('input')).toRightOf(firstNameLabel));// Or below for vertical form layoutsconst verticalInput = await driver.findElement( locateWith(By.tagName('input')).below(firstNameLabel));
// Find error message below an inputconst emailInput = await driver.findElement(By.id('email'));const errorMessage = await driver.findElement( locateWith(By.className('error')).below(emailInput));// Find input field associated with a labelIWebElement firstNameLabel = driver.FindElement( By.XPath("//label[text()='First Name']"));IWebElement firstNameInput = driver.FindElement( RelativeBy.WithLocator(By.TagName("input")).RightOf(firstNameLabel));// Or below for vertical form layoutsIWebElement verticalInput = driver.FindElement( RelativeBy.WithLocator(By.TagName("input")).Below(firstNameLabel));
// Find error message below an inputIWebElement emailInput = driver.FindElement(By.Id("email"));IWebElement errorMessage = driver.FindElement( RelativeBy.WithLocator(By.ClassName("error")).Below(emailInput));Table Cell Navigation
Table Navigation
Selenium 4 Medium
// Find delete button in the same row as "John Doe"WebElement nameCell = driver.findElement( By.xpath("//td[text()='John Doe']"));WebElement deleteBtn = driver.findElement( with(By.xpath("//button[text()='Delete']")).toRightOf(nameCell));
// Find value in column to the right of labelWebElement priceLabel = driver.findElement( By.xpath("//th[text()='Price']"));WebElement priceValue = driver.findElement( with(By.tagName("td")).below(priceLabel));# Find delete button in the same row as "John Doe"name_cell = driver.find_element( By.XPATH, "//td[text()='John Doe']")delete_btn = driver.find_element( locate_with(By.XPATH, "//button[text()='Delete']").to_right_of(name_cell))
# Find value in column to the right of labelprice_label = driver.find_element( By.XPATH, "//th[text()='Price']")price_value = driver.find_element( locate_with(By.TAG_NAME, "td").below(price_label))// Find delete button in the same row as "John Doe"const nameCell = await driver.findElement( By.xpath("//td[text()='John Doe']"));const deleteBtn = await driver.findElement( locateWith(By.xpath("//button[text()='Delete']")).toRightOf(nameCell));
// Find value in column to the right of labelconst priceLabel = await driver.findElement( By.xpath("//th[text()='Price']"));const priceValue = await driver.findElement( locateWith(By.tagName('td')).below(priceLabel));// Find delete button in the same row as "John Doe"IWebElement nameCell = driver.FindElement( By.XPath("//td[text()='John Doe']"));IWebElement deleteBtn = driver.FindElement( RelativeBy.WithLocator(By.XPath("//button[text()='Delete']")).RightOf(nameCell));
// Find value in column to the right of labelIWebElement priceLabel = driver.FindElement( By.XPath("//th[text()='Price']"));IWebElement priceValue = driver.FindElement( RelativeBy.WithLocator(By.TagName("td")).Below(priceLabel));When to Use Relative Locators
Good Use Cases
- Forms where labels and inputs are visually associated
- Tables with action buttons in rows
- Cards or tiles with associated controls
- Layouts where DOM structure doesn’t match visual layout
Limitations
- Viewport dependent - Results may vary if page isn’t fully visible
- Responsive layouts - Positions change at different screen sizes
- Dynamic content - Elements shifting can break locators
- Performance - Slightly slower than direct locators
Best Practices
- Use stable reference elements - The anchor element should have a reliable locator
- Test at consistent viewport - Ensure browser size is predictable
- Combine with explicit waits - Reference element must be visible
- Fallback to traditional locators - Use relative only when simpler options fail
- Don’t over-chain - More than 2 chained locators becomes fragile
Comparison with XPath Axes
| Relative Locator | XPath Equivalent |
|---|---|
below() | Visual position (not DOM) |
above() | Visual position (not DOM) |
toLeftOf() | Visual position (not DOM) |
toRightOf() | Visual position (not DOM) |
near() | No direct equivalent |
Key difference: XPath axes navigate the DOM tree, while relative locators use visual/rendered positions. An element can be “below” another visually but actually precede it in the DOM.
Next Steps
- CSS Selectors - Traditional CSS-based selection
- XPath Basics - DOM-based navigation
- Finding Elements - Element location fundamentals
- Explicit Waits - Wait for elements to be ready