How to click only visible elements with Puppeteer?

I’m working on a project where I need to click several elements on a webpage but only if they’re visible. This was pretty straightforward in Selenium using is_displayed, but I’m struggling to find a similar method in Puppeteer.

I tried using waitForSelector with the visible option set to true, like this:

try {
  await page.waitForSelector('#myElement', { visible: true, timeout: 5000 })
    .then(async (element) => {
      await element.click();
    });
} catch (error) {
  console.log('Element not visible or not found');
}

But it doesn’t work for simple elements like this:

<button class="close-popup">Got it</button>

Is there a reliable way to check if an element is visible before clicking it in Puppeteer? I couldn’t find anything similar to Selenium’s is_displayed method. Any help would be appreciated!

I’ve been down this road before, and it can be tricky. One solution that’s worked well for me is combining Puppeteer’s $ method with a custom visibility check function. Here’s what I’ve used:

const isElementVisible = async (page, selector) => {
  return page.evaluate((sel) => {
    const element = document.querySelector(sel);
    if (!element) return false;
    const rect = element.getBoundingClientRect();
    return rect.top >= 0 && rect.left >= 0 && rect.bottom <= window.innerHeight && rect.right <= window.innerWidth;
  }, selector);
};

// Usage
if (await isElementVisible(page, '.close-popup')) {
  await page.click('.close-popup');
} else {
  console.log('Element not visible or not found');
}

This approach checks if the element is within the viewport, which has been more reliable for me than just checking CSS properties. It’s saved me countless headaches with dynamic content. Give it a try and see if it helps with your specific use case!

hey there! i’ve had similar issues. have u tried using page.evaluate() to check visibility? something like:

await page.evaluate(() => {
const el = document.querySelector(‘.close-popup’);
return el && el.offsetParent !== null;
});

this checks if the element exists and is visible. if true, then click it. hope this helps!

I’ve encountered this challenge as well. One effective approach I’ve found is using the $eval method in Puppeteer. It allows you to execute a function in the context of the page and check for visibility. Here’s a snippet that’s worked reliably for me:

const isVisible = await page.$eval('.close-popup', el => {
  const style = window.getComputedStyle(el);
  return style && style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0';
});

if (isVisible) {
  await page.click('.close-popup');
}

This method checks the computed style properties to determine if an element is truly visible. It’s been more consistent than relying solely on waitForSelector in my experience.