DEV Community

Nathan Araújo
Nathan Araújo

Posted on

[Playwright] Element is outside of the viewport" in Playwright — why it happens and how to fix it

The problem

You have a checkbox in the DOM, for example, with id="AcceptedTermsOfUse", that is outside of the visible area of the page (viewport), for example with very large negative x coordinates like x = -9459.

When you try to run:

await page.locator('#AcceptedTermsOfUse').click();
Enter fullscreen mode Exit fullscreen mode

Playwright throws an error like:

Error: locator.click: Test timeout ...

“element is outside of the viewport”

or
"Call log:
- waiting for locator('input[type="checkbox"][name="AcceptedTermsOfUse"]')
- locator resolved to "

This means: the element exists, it is “visible” in terms of CSS (not display:none, not visibility:hidden), but it is not in a position where a user could physically click it, because it’s positioned or hidden off‑screen.


Why this happens

Common causes:

Off‑screen styling

The input is styled with position: absolute (or similar), using left: -xxxxx or transform that pushes it outside the viewport.

Styled label + hidden input

Many UI frameworks hide the real off-screen and use only a label plus pseudo-elements (::before, ::after) to render the visible checkbox square. This allows them to style a “fancy checkbox” without relying on the browser’s native styling. The user clicks on the label, which propagates the click to the hidden input. So the input is technically visible (not display:none), but positioned outside the viewport so the user never interacts with it directly.

Playwright actionability checks

Before performing locator.click(), Playwright ensures:

  • the element is visible
  • enabled
  • stable (not moving/animating)
  • within the viewport or can be scrolled into it

If any of these fail, Playwright won’t click.

Known tricky cases

Sometimes elements are technically visible but still unreachable due to layout/CSS. This is common with checkboxes hidden for custom styling.


Real example

In this case, the checkbox was:

  • Visible in CSS terms
  • Enabled
  • But with boundingBox().x = -9459 — far to the left
  • Absolutely positioned
  • No scrollable parent to bring it into view

So Playwright couldn’t click because it wasn’t physically actionable.

Possible solution

1. Use page.evaluate with element.click()

await page.evaluate(() => {
  const checkbox = document.getElementById("AcceptedTermsOfUse");
  if (checkbox) checkbox.click();
});
Enter fullscreen mode Exit fullscreen mode

This works even if the input is off‑screen, because it fires a DOM click programmatically.


2. Manually set checked and dispatch events

await page.evaluate(() => {
  const checkbox = document.getElementById("AcceptedTermsOfUse") as HTMLInputElement;
  if (checkbox) {
    checkbox.checked = true;
    checkbox.dispatchEvent(new Event('change', { bubbles: true }));
  }
});
Enter fullscreen mode Exit fullscreen mode

Forces the state and triggers a change event.


Investigation

You can investigate this behavior directly in the browser console. For example, open DevTools and run:

document.getElementById("AcceptedTermsOfUse").click();
Enter fullscreen mode Exit fullscreen mode

You’ll notice the checkbox gets checked and any attached event listeners fire — even if the element is off-screen.


Why document.getElementById("AcceptedTermsOfUse").click() works off-screen, but Playwright’s locator.click() does not?

When you call element.click() in the browser (either in the console or inside page.evaluate()), the browser’s DOM engine executes HTMLElement.prototype.click().

This method programmatically triggers all associated events (mousedown, mouseup, click, input, change, depending on the element) and updates the element state. Importantly:

  • The browser does not require the element to be inside the viewport.
  • The DOM allows simulating a click even if the element is positioned off-screen.

Why Playwright behaves differently

Playwright aims to simulate real user interaction, not just fire DOM events. When you call:

await page.locator('#AcceptedTermsOfUse').click();
Enter fullscreen mode Exit fullscreen mode

Playwright performs actionability checks:

  1. The element must be visible, enabled, stable (not moving), and not covered by other elements.
  2. The element must be within the viewport, or Playwright will attempt to scroll it into view.
  3. If Playwright cannot make the element actionable, it throws: "element is outside of the viewport".

These checks exist so tests mimic how a real user would interact with the page — for example, preventing clicks through invisible or off-screen elements.

Top comments (0)