In Selenium 4, what does RelativeLocator's near() match by default, and how are its results ordered?
answer
- Not a direction, a radius
- The anchor's box, grown on all sides
- A default measured in CSS pixels
- Fifty, and an overload to change it
- Sorted by centre-to-centre distance
basics
~10 sSelenium's near() keeps any element whose rectangle overlaps the anchor's rectangle grown by 50 pixels on every side, excluding the anchor itself. Results come back sorted by centre-to-centre distance, closest first.
solid answer
~40 s`near` is the one proximity filter that is not an axis ordering. The injected script expands the anchor's `getBoundingClientRect()` box by the distance on all four sides and keeps every candidate whose own box intersects that region, so direction does not matter and an overlapping candidate still qualifies; the anchor is excluded from its own results. `near(WebElement)` and `near(By)` use the Java constant `CLOSE_IN_PIXELS`, which is **50** CSS pixels measured from the anchor's edges, and the overloads `near(anchor, atMostDistanceInPixels)` let you set it — the value must be positive or you get an `IllegalArgumentException`. Matches are then sorted by the straight-line distance between centre points, nearest first, so `findElement` returns the closest one rather than the first in document order.
code
java · 17 linesimport static org.openqa.selenium.support.locators.RelativeLocator.with;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
public class BidPanelProximity {
public static WebElement incrementFieldByItsLabel(WebDriver driver) {
return driver.findElement(with(By.tagName("input")).near(By.id("lbl-bid-increment")));
}
public static WebElement paddleFieldWithinTwentyPixels(WebDriver driver) {
WebElement paddleLabel = driver.findElement(By.id("lbl-paddle"));
return driver.findElement(with(By.tagName("input")).near(paddleLabel, 20));
}
}go deeper
Recall that near is the relative filter for "close to this element in any direction", that it has a built-in default distance, and that a pixel distance can be supplied explicitly.
Be ready to explain the mechanics: the anchor's rectangle expanded by 50 pixels on every side, intersection as the test, the anchor excluded, and results sorted nearest first by centre distance.
An interviewer expects you to reason about when 50 pixels is wrong for a real layout, to notice that the sort anchor is the last filter in a chain, and to explain a surprising first result from the rectangles.
Own the fact that a pixel budget is a tuning knob your suite now carries. Be able to say what makes a chosen distance defensible and what it silently couples the locator to.
## `near` asks a containment question, not an ordering question `near` is the odd one out among Selenium's proximity filters. `above`, `below`, `toLeftOf` and `toRightOf` order two rectangles along one axis. `near` instead takes the anchor's client bounding rectangle, **grows it by the distance on all four sides**, and keeps every candidate whose own rectangle **intersects** that grown region. For an anchor at `left`, `top`, `width`, `height` and a distance `d`, the expanded region runs from `left - d` to `left + width + d` horizontally and from `top - d` to `top + height + d` vertically. A candidate survives when its box overlaps that region on both axes at once. - **Overlapping elements qualify.** Unlike the directional filters, which reject any shared pixel, `near` is happy with a candidate sitting on top of the anchor. - **Direction is irrelevant.** A bid-increment field above the label and one below it are equally near. - **The anchor never matches itself.** The atom compares the resolved anchor with each candidate and drops the identity case, so `near` cannot return the thing you anchored on. ## The default distance is 50 pixels `near(WebElement)` and `near(By)` delegate to the two-argument overloads using a constant the Java source names `CLOSE_IN_PIXELS`, whose value is **50**; the injected `findElements.js` atom carries the same 50 as its own fallback. The explicit overloads `near(WebElement, int atMostDistanceInPixels)` and `near(By, int atMostDistanceInPixels)` let you set it yourself, and the value is validated as **positive** — passing zero or a negative number raises `IllegalArgumentException` rather than quietly meaning "anywhere". | Call | Distance used | Anchor form | |---|---|---| | `near(element)` | 50 px | a `WebElement` you already found | | `near(By.id("lbl-paddle"))` | 50 px | a locator, resolved to its first match | | `near(element, 20)` | 20 px | a `WebElement` you already found | | `near(By.id("lbl-paddle"), 120)` | 120 px | a locator, resolved to its first match | Fifty pixels is a **CSS-pixel budget measured from the anchor's edges**, not from its centre, so a wide anchor such as a full-width lot header reaches 50 px beyond an already large box. On a dense bidding panel that can easily swallow the neighbouring lot's controls; on a sparse one it can fall short of a field separated by a generous label gap. The number is a starting point you are expected to tune with the explicit overload. ## Ordering is by centre-to-centre distance Filtering decides *which* elements come back; a separate step decides *in what order*. After the filters run, the atom sorts the survivors by the straight-line distance between centre points — the anchor's centre against each match's centre — nearest first. Two details matter: 1. The sort uses the anchor of the **last filter in the chain**. In `with(By.tagName("input")).below(header).near(label)`, the ordering is by distance to `label`; swap the two filters and the same matched set comes back in a different order. 2. Zero-sized boxes are guarded: the centre calculation treats width and height as at least one pixel, so a collapsed element still gets a defined centre rather than skewing the comparison. Because the list is sorted, `driver.findElement(with(...).near(...))` returns the **closest** match, not the first in document order. When the filtered set is empty, `findElement` raises `NoSuchElementException` with the message "Cannot locate an element using", while `findElements` simply returns an empty list. ## Filter test versus sort key The two halves use different geometry, and conflating them is the usual source of confusion. | Question | Geometry used | |---|---| | Is this candidate near the anchor? | rectangle intersection with the anchor's box expanded by the distance | | Which near candidate comes first? | Euclidean distance between the two centre points | So a tall, narrow element whose edge just clips the expanded region can rank ahead of a compact element whose centre is further away, because the two questions are answered with different measurements. ## Using it on a bidding panel 1. Anchor on the label, not the control: `with(By.tagName("input")).near(By.id("lbl-bid-increment"))` is the canonical shape, since a label almost always has stable text or an id while the field beside it may have neither. 2. Narrow the root locator first. `near` does not care about direction, so a loose root such as `By.tagName("div")` will pull in wrappers you did not want. 3. Set the distance deliberately when the panel is dense — `near(paddleLabel, 20)` keeps the paddle field and rejects the bid field one row down. 4. If the result is a surprise, print the anchor's `getRect()` and the candidate's `getRect()` and check the intersection by hand; the arithmetic is simple and it is the only thing the filter is doing.
- Is the 50-pixel default measured from the anchor's centre or its edges?From its edges. The anchor's bounding rectangle is expanded outward by the distance on all four sides, so a wide element such as a full-width lot header reaches 50 pixels beyond an already large box. That is why the same default feels generous on a sparse panel and far too greedy on a dense one, and why the explicit overload exists.
- In a chain such as below(header).near(label), which anchor decides the ordering?The last one, `label`. Filtering applies every filter in the chain, but the sort is measured from the anchor of the final filter only. Reordering the chain therefore leaves the matched set unchanged while changing which element comes first, and so which one `findElement` returns.
- What happens if you pass zero as the distance to near()?It throws `IllegalArgumentException`. Selenium validates the distance as positive rather than treating zero as "touching only" or as "no limit", so a computed distance that can reach zero has to be guarded before the call.
saying these in an interview costs you the question
- Says near() measures from the anchor's centre point
- Quotes a default other than 50 pixels
- Thinks near() can return the anchor element itself
- Assumes results come back in document order
- Believes near() implies a direction such as below