Skip to main content
SeleniumDecoded

Wait for a Loading Spinner to Disappear

Wait for an overlay or spinner to be gone before interacting, including the case where it never appeared.

Stable Verified against Selenium 4.48.0

Problem

After clicking, the app shows a full-screen spinner. Clicking the next button while it is up produces ElementClickInterceptedException. Sometimes the spinner is so fast it is gone before your wait starts, and a “wait for visible, then wait for invisible” sequence times out.

Solution

Wait only for invisibility. The condition is satisfied both when the spinner is hidden and when it does not exist, so it handles the fast-spinner case.

Wait for the overlay to go
Selenium 3 & 4 Stable
By spinner = By.cssSelector(".loading-overlay, .spinner");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15));
driver.findElement(By.id("apply-filters")).click();
wait.until(ExpectedConditions.invisibilityOfElementLocated(spinner)); // true if hidden OR absent
driver.findElement(By.id("export")).click();
// Reusable helper on a base page
protected void waitForLoading() {
wait.until(ExpectedConditions.invisibilityOfElementLocated(spinner));
}
spinner = (By.CSS_SELECTOR, ".loading-overlay, .spinner")
wait = WebDriverWait(driver, 15)
driver.find_element(By.ID, "apply-filters").click()
wait.until(EC.invisibility_of_element_located(spinner)) # true if hidden OR absent
driver.find_element(By.ID, "export").click()
const spinner = By.css('.loading-overlay, .spinner');
await driver.findElement(By.id('apply-filters')).click();
await driver.wait(async () => {
const els = await driver.findElements(spinner);
for (const el of els) if (await el.isDisplayed()) return false;
return true;
}, 15000, 'spinner still visible');
await driver.findElement(By.id('export')).click();
var spinner = By.CssSelector(".loading-overlay, .spinner");
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(15));
driver.FindElement(By.Id("apply-filters")).Click();
wait.Until(d => d.FindElements(spinner).All(e => !e.Displayed)); // true if hidden OR absent
driver.FindElement(By.Id("export")).Click();

Why It Works

invisibilityOfElementLocated returns true when the element is not displayed, throws-and-ignores NoSuchElement (treated as invisible), and handles stale references the same way. It never requires the spinner to have been seen.

Gotchas

  • Match all spinner variants in one selector; apps often have several.
  • Some overlays fade out with CSS transitions and remain “displayed” at 1% opacity. If clicks still get intercepted after the wait, wait for the element to be removed (findElements returns empty) or for opacity to be 0 via getCssValue.
  • Put the wait inside page object methods that trigger loading, so tests never have to remember it.

Learn the theory