Heuristic:Webdriverio Webdriverio Click Interception Workaround
| Knowledge Sources | |
|---|---|
| Domains | Browser_Automation, Debugging |
| Last Updated | 2026-02-12 01:00 GMT |
Overview
Automatic workaround for "element click intercepted" errors caused by fixed-position headers, footers, or overlapping elements — scrolls the target element to center viewport before retrying.
Description
When a standard WebDriver `elementClick` command fails with an "element click intercepted" error, WebdriverIO automatically applies a workaround: it scrolls the target element into the center of the viewport using `scrollIntoView({ block: 'center', inline: 'center' })` and retries the click. This handles the common scenario where sticky headers, footers, cookie banners, or other fixed-position elements overlay the target element after it has been scrolled into view with the default nearest alignment. The workaround is only applied for intercepted click errors — all other errors are re-thrown to the middleware for normal handling.
Usage
This heuristic is automatically applied by WebdriverIO's click command. Be aware of it when:
- Debugging click failures: If you see "element click intercepted" followed by a successful click, this workaround fired.
- Native mobile apps: The workaround does not apply to native mobile apps — the implicitWait throws before the workaround can execute.
- Manual scrolling needed: If the workaround still fails (e.g., element covered by a dynamic overlay), manually remove the overlay via `execute` or scroll with a custom offset.
The Insight (Rule of Thumb)
- Action: When `elementClick` throws "element click intercepted", call `element.scrollIntoView({ block: 'center', inline: 'center' })` then retry the click.
- Value: `block: 'center'` ensures the element is vertically centered, avoiding overlap from fixed headers/footers.
- Trade-off: Adds a scroll action before retry, which may cause slight visual shift. Does not work for native mobile apps.
- Scope: Web browsers only (desktop and mobile web). Not applicable to native Appium sessions.
Reasoning
The default `scrollIntoView` behavior uses `nearest` alignment, which places the element at the bottom of its ancestor's scroll container. This frequently positions the element behind fixed-position headers or footers. By using `center` alignment, the element is placed in the middle of the viewport, maximizing the distance from any fixed-position elements at the top or bottom. Additionally, `browser.action().move()` is known to be flaky and sometimes unable to scroll the pointer into view, making the explicit `scrollIntoView` a more reliable approach.
Evidence from code comments:
From `packages/webdriverio/src/commands/element/click.ts:123-130`:
/**
* Workaround function, because sometimes browser.action().move() flaky and isn't able to scroll pointer to into view
* Moreover the action with 'nearest' behavior by default where element is aligned at the bottom of its ancestor.
* and could be overlapped. Scroll to center should definitely work even if element was covered with sticky header/footer
*/
async function workaround(element: WebdriverIO.Element) {
await element.scrollIntoView({ block: 'center', inline: 'center' })
}
Selective error handling from `packages/webdriverio/src/commands/element/click.ts:144-151`:
if (!err.message.includes('element click intercepted')) {
// we only apply the workaround when the click got intercepted
// so that the middleware can handle any other errors
throw err
}
await workaround(element)
return element.elementClick(element.elementId)