Skip to main content
SeleniumDecoded

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

LocatorDescription
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 first
WebElement emailLabel = driver.findElement(By.id("email-label"));
// Find input below the email label
WebElement emailInput = driver.findElement(
with(By.tagName("input")).below(emailLabel)
);
// Find button to the right of cancel button
WebElement cancelBtn = driver.findElement(By.id("cancel"));
WebElement submitBtn = driver.findElement(
with(By.tagName("button")).toRightOf(cancelBtn)
);
// Find label above an input field
WebElement passwordInput = driver.findElement(By.id("password"));
WebElement passwordLabel = driver.findElement(
with(By.tagName("label")).above(passwordInput)
);
// Find element to the left
WebElement priceValue = driver.findElement(By.className("price"));
WebElement priceLabel = driver.findElement(
with(By.tagName("span")).toLeftOf(priceValue)
);
from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with
# Find the reference element first
email_label = driver.find_element(By.ID, "email-label")
# Find input below the email label
email_input = driver.find_element(
locate_with(By.TAG_NAME, "input").below(email_label)
)
# Find button to the right of cancel button
cancel_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 field
password_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 left
price_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 first
const emailLabel = await driver.findElement(By.id('email-label'));
// Find input below the email label
const emailInput = await driver.findElement(
locateWith(By.tagName('input')).below(emailLabel)
);
// Find button to the right of cancel button
const cancelBtn = await driver.findElement(By.id('cancel'));
const submitBtn = await driver.findElement(
locateWith(By.tagName('button')).toRightOf(cancelBtn)
);
// Find label above an input field
const passwordInput = await driver.findElement(By.id('password'));
const passwordLabel = await driver.findElement(
locateWith(By.tagName('label')).above(passwordInput)
);
// Find element to the left
const 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 first
IWebElement emailLabel = driver.FindElement(By.Id("email-label"));
// Find input below the email label
IWebElement emailInput = driver.FindElement(
RelativeBy.WithLocator(By.TagName("input")).Below(emailLabel)
);
// Find button to the right of cancel button
IWebElement cancelBtn = driver.FindElement(By.Id("cancel"));
IWebElement submitBtn = driver.FindElement(
RelativeBy.WithLocator(By.TagName("button")).RightOf(cancelBtn)
);
// Find label above an input field
IWebElement passwordInput = driver.FindElement(By.Id("password"));
IWebElement passwordLabel = driver.FindElement(
RelativeBy.WithLocator(By.TagName("label")).Above(passwordInput)
);
// Find element to the left
IWebElement 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 label
WebElement 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 label
label = 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 label
const 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 label
IWebElement 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 another
WebElement 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 cancel
WebElement 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 another
header = 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 cancel
name_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 another
const 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 cancel
const 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 another
IWebElement 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 cancel
IWebElement 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 label
WebElement firstNameLabel = driver.findElement(
By.xpath("//label[text()='First Name']")
);
WebElement firstNameInput = driver.findElement(
with(By.tagName("input")).toRightOf(firstNameLabel)
);
// Or below for vertical form layouts
WebElement verticalInput = driver.findElement(
with(By.tagName("input")).below(firstNameLabel)
);
// Find error message below an input
WebElement emailInput = driver.findElement(By.id("email"));
WebElement errorMessage = driver.findElement(
with(By.className("error")).below(emailInput)
);
# Find input field associated with a label
first_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 layouts
vertical_input = driver.find_element(
locate_with(By.TAG_NAME, "input").below(first_name_label)
)
# Find error message below an input
email_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 label
const 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 layouts
const verticalInput = await driver.findElement(
locateWith(By.tagName('input')).below(firstNameLabel)
);
// Find error message below an input
const emailInput = await driver.findElement(By.id('email'));
const errorMessage = await driver.findElement(
locateWith(By.className('error')).below(emailInput)
);
// Find input field associated with a label
IWebElement 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 layouts
IWebElement verticalInput = driver.FindElement(
RelativeBy.WithLocator(By.TagName("input")).Below(firstNameLabel)
);
// Find error message below an input
IWebElement 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 label
WebElement 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 label
price_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 label
const 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 label
IWebElement 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

  1. Use stable reference elements - The anchor element should have a reliable locator
  2. Test at consistent viewport - Ensure browser size is predictable
  3. Combine with explicit waits - Reference element must be visible
  4. Fallback to traditional locators - Use relative only when simpler options fail
  5. Don’t over-chain - More than 2 chained locators becomes fragile

Comparison with XPath Axes

Relative LocatorXPath 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