Selenium 4 - Relative Locators

Selenium 4 offers a new way of locating elements by using natural language terms such as “above”, “below”, “left of”, “right of”, and “near”. This article describes how to use the new Relative Locators.

This functionality brings a new way to locate elements to help you find the ones that are nearby other elements. The available locators are:

above
below
toLeftOf
toRightOf
near

The concept behind this method is to allow you to find elements based on how one would describe them on a page. It is more natural to say: “find the element that is below the image”, rather than “find the INPUT inside the DIV with the ‘id’ of ‘main’”. In general, you could think about them as a way to locate elements based on the visual placement on the page.

For additional examples, including chaining relative locators in these languages, look at our Selenium 4 Documentation.

We will use the following login form to understand how Relative Locators work:

Asset > Selenium 4 login-form-relative-locators

Above

We would like to find the email address field, which is above the password field. To do that, we find the password field through its id, and then we use the above relative locator.

Java

import static org.openqa.selenium.support.locators.RelativeLocator.with;
WebElement password = driver.findElement(By.id("password"));
WebElement email = driver.findElement(with(By.tagName("input")).above(passwordField));

Python

from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with
passwordField = driver.find_element(By.ID, "password")
emailAddressField = driver.find_element(locate_with(By.TAG_NAME,  "input").above(passwordField))

C#

using static OpenQA.Selenium.RelativeBy;
IWebElement passwordField = driver.FindElement(By.Id("password"));
IWebElement emailAddressField = driver.FindElement(RelativeBy(By.TagName("input")).Above(passwordField)); 

Ruby

password_field= driver.find_element(:id, "password")
email_address_field = driver.find_element(relative: {tag_name: "input", above:password_field})

JavaScript

let passwordField = driver.findElement(By.id('password'));
let emailAddressField = await driver.findElement(locateWith(By.tagName('input')).above(passwordField));

Below

Going the other way around, let's find the password field, which is below the email address field.

Java

import static org.openqa.selenium.support.locators.RelativeLocator.with;
WebElement emailAddressField = driver.findElement(By.id("email"));
WebElement passwordField = driver.findElement(with(By.tagName("input"))
                                          	.below(emailAddressField));

Python

from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with
emailAddressField = driver.find_element(By.ID, "email")
passwordField = driver.find_element(locate_with(By.TAG_NAME, "input").below(emailAddressField))

C#

using static OpenQA.Selenium.RelativeBy;
IWebElement emailAddressField = driver.FindElement(By.Id("email"));
IWebElement passwordField =
driver.FindElement(RelativeBy(By.TagName("input")).Below(emailAddressField)); 

Ruby

email_address_field = driver.find_element(:id, "email")
password_field = driver.find_element(relative: {tag_name: "input", below: email_address_field})

JavaScript

let emailAddressField = driver.findElement(By.id('email'));
let passwordField = await driver.findElement(locateWith(By.tagName('input')).below(emailAddressField));

To the Left Of

Let’s consider the case where we want to find the element on the left side of the “Submit” button.

Java

import static org.openqa.selenium.support.locators.RelativeLocator.with;
WebElement submitButton = driver.findElement(By.id("submit"));
WebElement cancelButton = driver.findElement(with(By.tagName("button"))
                                        	.toLeftOf(submitButton));

Python

from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with
submitButton = driver.find_element(By.ID, "submit")
cancelButton = driver.find_element(locate_with(By.TAG_NAME, "button").
                               	to_left_of(submitButton))

C#

using static OpenQA.Selenium.RelativeBy;
IWebElement emailAddressField = driver.FindElement(By.Id("email"));
IWebElement passwordField =
driver.FindElement(RelativeBy(By.TagName("input")).Below(emailAddressField));

Ruby

submit_button= driver.find_element(:id, "submit")
cancel_button = driver.find_element(relative: {tag_name: 'button', left:submit_button})

JavaScript

let submitButton = driver.findElement(By.id('submit'));
let cancelButton = await driver.findElement(locateWith(By.tagName('button')).toLeftOf(submitButton));

To the Right Of

Now we'll consider the opposite case, where we want to find the element on the right side of the “Cancel” button.

Java

import static org.openqa.selenium.support.locators.RelativeLocator.with;
WebElement cancelButton = driver.findElement(By.id("cancel"));
WebElement submitButton = driver.findElement(with(By.tagName("button")).toRightOf(cancelButton));

Python

from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with
cancelButton = driver.find_element(By.ID, "cancel")
submitButton = driver.find_element(locate_with(By.TAG_NAME, "button").
                               	to_right_of(cancelButton))

C#

using static OpenQA.Selenium.RelativeBy;
IWebElement cancelButton = driver.FindElement(By.Id("cancel"));
IWebElement submitButton = driver.FindElement(RelativeBy(By.TagName("button")).RightOf(cancelButton)); 

Ruby

cancel_button = driver.find_element(:id, "cancel")
submit_button = driver.find_element(relative: {tag_name: 'button', right:cancel_button})

JavaScript

let cancelButton = driver.findElement(By.id('cancel'));
let submitButton = await driver.findElement(locateWith(By.tagName('button')).toRightOf(cancelButton));

Near

near is helpful when we need to find an element that is at most 50px away from the specified element. In this case, we would like to find the email address field by first finding the label of that field.

Java

import static org.openqa.selenium.support.locators.RelativeLocator.with;
WebElement emailAddressLabel = driver.findElement(By.id("lbl-email"));
WebElement emailAddressField = driver.findElement(with(By.tagName("input")).near(emailAddressLabel));

Python

from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with
emailAddressLabel = driver.find_element(By.ID, "lbl-email")
emailAddressField = driver.find_element(locate_with(By.TAG_NAME, "input").
                                   	near(emailAddressLabel))

C#

using static OpenQA.Selenium.RelativeBy;
IWebElement emailAddressLabel = driver.FindElement(By.Id("lbl-email"));
IWebElement emailAddressField = driver.FindElement(RelativeBy(By.TagName("input")).Near(emailAddressLabel)); 

Ruby

email_address_label = driver.find_element(:id, "lbl-email")
email_address_field = driver.find_element(relative: {tag_name: 'input', near: email_address_label})

JavaScript

let emailAddressLabel = driver.findElement(By.id("lbl-email"));
let emailAddressField = await driver.findElement(with(By.tagName("input")).near(emailAddressLabel));

An updated set of methods, utilities and examples can be found at the official documentation.

Check out our comprehensive guide to Selenium 4 for more information.





Written by

Diego Molina and Titus Fortner


Topics

SeleniumAutomated testing