You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
By clicking “Sign up for GitHub”, you agree to our
terms of service
and
privacy statement
. We’ll occasionally send you account related emails.
Already on GitHub?
Sign in
to your account
What steps will reproduce the problem?
// compare with .to-screenshot size
await page.setViewport({width: 500, height: 500});
await page.setContent(`
something above
<style>div.spacer {
border: 2px solid blue;
background: red;
height: 600px;
div.to-screenshot {
border: 2px solid blue;
background: green;
width: 50px;
height: 1000px;
margin-left: 1000px;
</style>
<div class="spacer"></div>
<div class="to-screenshot"></div>
<div class="spacer"></div>
`);
const elementHandle = await page.$('div.to-screenshot');
const screenshot = await elementHandle.screenshot();
I'm using
elementHandle.screenshot()
which is working, but if the element is larger than the viewport, it won't capture all of it. This make sense if you look at the source and see that it's using
page.screenshot
with a
clip
, and you know that clip doesn't work with
fullPage
, but it's not intuitive, and doesn't seem like a good default behavior.
Would it be possible to get
elementHandle.screenshot
to capture the whole element? It already tries to ignore scroll position, but viewport size limits it.
I tried making it use
Emulation.setDeviceMetricsOverride
, but then clip stopped working. Guessing this is why
clip
+
fullPage
errors.
On the project I need this for, I ended up doing:
const bounds = await el.boundingBox();
const initial = Object.assign({}, page.viewport());
await page.setViewport({
width: Math.max(Math.ceil(bounds.width), initial.width),
height: Math.max(Math.ceil(bounds.height), initial.height),
});
const imageRes = await el.screenshot({ type: 'jpeg', quality: 90 });
await page.setViewport(initial);
return imageRes;
Of course, this would impact media queries and 'resize' events, so not high enough quality to be included in puppeteer's source, I think.
I don't know what a good solution would be, but I use element screenshots a lot so I'm happy to implement any solutions you come up with. Thanks for the great tool!
Maybe we should resize the page if the clip rect is larger than the page viewport, as we do with fullpage screenshots. We call the same method as setViewport does when doing fullPage screenshots, so I think your solution is fine. We also already send a real scroll into the page before doing element screenshots, so I am not worried about them becoming detectable by the page. Would welcome a PR!
Modifies ElementHande::screenshot to capture the full element, even if
it's larger than the current viewport, or it falls off screen. Uses
window.scrollTo instead of scrollIntoViewIfNeeded because it must be
as much inside the viewport as possible. Partially visibile isn't good
for this use case. Resets the viewport size and scroll position after
it's finished.
Fixes puppeteer#1779
feat: make ElementHandle.screenshot work with large elements
This patch increases the viewport size if the element is bigger than
viewport.
Fixes #1779
I'm running the latest version of puppeteer and this seems to be happening on my end - my element is larger than the viewport sees so anything that isn't being 'seen' on screen is clipped. The dimensions of the image are correct, however, most of the image is missing.
Is anyone experiencing this?