Answer
Handling Dynamic Elements in Selenium
Dynamic elements have attributes (id, class, name) that change on every page load — making static locators break. Here are the strategies to handle them:
Strategy 1 — XPath with contains()
Java
// Element whose id changes like "btn_123", "btn_456"
WebElement btn = driver.findElement(
By.xpath("//button[contains(@id, 'btn_')]")
);
// Element whose class partially matches
WebElement el = driver.findElement(
By.xpath("//div[contains(@class, 'active-item')]")
);
Strategy 2 — starts-with()
Java
// id="product_2024_item" — prefix is stable
WebElement item = driver.findElement(
By.xpath("//li[starts-with(@id, 'product_')]")
);
Strategy 3 — XPath by visible text
Java
// Locate by what the user sees, not a dynamic attribute
WebElement link = driver.findElement(
By.xpath("//a[text()='View Details']")
);
// Partial text match
WebElement btn = driver.findElement(
By.xpath("//button[contains(text(),'Submit')]")
);
Strategy 4 — WebDriverWait to stabilize
Java
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement el = wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.xpath("//div[contains(@class,'loaded')]")
)
);
Strategy 5 — CSS attribute selector
Java
// Match data-* attributes that are stable even when id changes
WebElement el = driver.findElement(
By.cssSelector("[data-testid='submit-button']")
);
Best Practice — Ask Dev for data-testid
The most reliable fix: ask developers to add stable data-testid or data-qa attributes specifically for automation. This decouples test locators from UI implementation details.
Quick Decision Tree
- ✓Partial id/class →
contains()orstarts-with() - ✓Visible text →
text()orcontains(text(), '') - ✓Loading race →
WebDriverWait+ExpectedConditions - ✓Random attribute →
data-testidfrom dev
