puppeteer: Full page screenshot is not using viewport size for `vw` and `vh` CSS.
Using fullPage: true
option with Page.screenshot seems to be messing vw
and vh
CSS units, even though page size is set with Page.setViewport.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 14
- Comments: 21 (3 by maintainers)
Commits related to this issue
- Work around full page screenshot causing vh,vw to scale up to page content https://github.com/GoogleChrome/puppeteer/issues/703#issuecomment-366041479 — committed to ycccamp/ycc2-landing by dtinth 5 years ago
- Enforce page width Recommended on https://github.com/puppeteer/puppeteer/issues/703#issuecomment-366037988 did indeed worked. — committed to thiagomorato/puppeteer by thiagomorato 4 years ago
My current workaround – instead of using
fullPage
I measure the body bounding box and use that as a clipping argument:Hey! Any progress here? 😃 Maybe somebody knows the workaround?
add this code before screenshot to fix:
await page.evaluate(async () => { var allElems = window.document.getElementsByTagName("*"); for (var i = 0, max = allElems.length; i < max; i++) { var hEleme = window.getComputedStyle(allElems[i]).height; if(hEleme != 'auto'){ var numdEleme = Number(hEleme.slice(0, -2)); if(numdEleme > 100 && numdEleme < 1000){ allElems[i].style.setProperty("height", numdEleme + 'px', "important"); } } } return true; });
An example page that’s using
vh
CSS units - http://jsbin.com/fawerivecu/edit?html,css,output.Script:
Expected Result:
Actual Result:
This package may help you: https://github.com/morteza-fsh/puppeteer-full-page-screenshot
For what’s it’s worth, I don’t think this is an actual bug, but rather the expected (or unexpected) behavior of the viewport.
If you open a Chrome page in a vertical monitor at full height, and you open a website using
100vh
in a section (for example the hero), the section will take the entire height of the screen (as expected). When people implement their websites with Viewport units, they don’t account for supermassive vertical screens, so it doesn’t make sense to think of a scenario where the page isn’t visualized with at least one screen fold scroll (which is what Puppeteer is doing when fullPage is true)There are many ways to get around this but not all the strategies will cover 100% of the cases. It seems that the issue comes from Puppeteer interpreting that fullPage=true means the height of the viewport is equivalent to the height of the window.
The solution that puppeteer could provide is to receive an extra parameter besides the fullPage=true, with a pseudo-viewport height in pixels, then when rendering, before snapping it could swap any references that are using
100vh
, to the passed pseudo-viewport height in pixels. I say pseudo-viewport value but this could be simply assuming that the height value you pass when you doPage.setViewport
.What I don’t know is how expensive would it be to make that swap in terms of performance.
There’s actually a PostCSS plugin that does that something similar fix an issue with a CMS. Not the same problem but within the same realm of what’s going on here: https://www.npmjs.com/package/postcss-vh-to-px
Thanks, that’s a bug with full page screenshots. Filed upstream: crbug.com/763421
The only workaround I have been able to get working is to change this line https://github.com/GoogleChrome/puppeteer/blob/master/lib/Page.js#L713 from this:
to this:
The current code is resizing the height correctly because you want a full-height screenshot, but it’s also resizing the screenshot’s width to the size of the content, ignoring the viewport settings. I think the width should maintain the desired viewport size.
@schnerd - That worked like a charm for me! Exactly what I needed. Big Thanks