Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

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

Is it possible to set the viewport size with <meta> tags? #42

Closed
abrom opened this issue Feb 14, 2020 · 6 comments · Fixed by #43
Closed

Is it possible to set the viewport size with <meta> tags? #42

abrom opened this issue Feb 14, 2020 · 6 comments · Fixed by #43

Comments

@abrom
Copy link
Contributor

abrom commented Feb 14, 2020

Is it possible to set the viewport size with <meta> tags? Ex:

<meta name="grover-viewport-width" content=640>
<meta name="grover-viewport-height" content=480>

This doesn't work because 640 and 480 are converted to strings and puppeteer throws an error "Protocol error (Emulation.setDeviceMetricsOverride): Invalid parameters width: integer value expected; height: integer value expected"

(Asking here because it comes up when searching, so hopefully that will help others benefit from the answer)

Originally posted by @willkoehler in #26 (comment)

@abrom
Copy link
Contributor Author

abrom commented Feb 14, 2020

Yes definitely possible. Something I'd already done for the scale attribute:

options['scale'] = options['scale'].to_f

You're welcome to create a PR for it, otherwise I can take a look when I get some time.

@willkoehler
Copy link
Contributor

willkoehler commented Feb 14, 2020

Thinking more about this, I actually want to set the viewport size automatically based on the content. One way to do this would be to move the viewport setting in convert_function below the call to await page.goto ... and then use a specifically-named container div to grab the height/width of the desired content. Something like:

const grover_container = await page.getElementById('grover_container');
if(grover_container) { 
   const box = await grover_container.boundingBox();
   await page.setViewport({height: box.height, width: box.width});
}
else
{
  const viewport = options.viewport; delete options.viewport;
  if (viewport != undefined) {
    await page.setViewport(viewport);
  }
}

Even better would be to set the screenshot clip: to the bounding box including x and y position like in this example https://stackoverflow.com/a/52583069/935514. But I'm not sure where to put that logic in the grover code.

If this looks like a good approach, I'm happy to work out the details and open a PR.

@abrom
Copy link
Contributor Author

abrom commented Feb 14, 2020

Sounds like you've got a chicken and egg situation here. The page will layout based on the content so what you're suggesting doesn't really make sense. That is to say, there will be a default viewport size which the page will layout to, you're then trying to get the width and height based on what it's just rendered. Something like that would be heavily dependant on the content so I can't see it being something 'generic' enough to fit into the master branch (ie in the gem). Think about what happens with pages that specify '100% width' or '100% height'. They would just 'fit' to the initial viewport.

You are of course welcome to fork the project and apply your code in your fork. Likely somewhere here-ish: https://github.com/Studiosity/grover/blob/master/lib/grover.rb#L120 ie somewhere after the page has rendered but before it 'converts' to what ever format you want.

If you're just trying to get a screenshot of the entire page, you're likely better just enabling the fullPage option per: https://github.com/puppeteer/puppeteer/blob/v2.1.0/docs/api.md#pagescreenshotoptions

@willkoehler
Copy link
Contributor

That's a good point. I originally thought there would be a chicken and egg problem as well, but it turns out it works just fine as long as your page isn't responsive in some way that alters the content based on the window size (which I think applies to many pages?).

For responsive pages, this technique could always be modified to use the clip parameter of screenshot(). In my case I'm creating images of React components to go into emails. Every page has a well-defined containing box that can be captured as an image. For example:

jeff

I have a proof of concept using viewport. I added the follow code at the point you recommended: https://github.com/Studiosity/grover/blob/master/lib/grover.rb#L120

const grover_container = await page.$('#grover_container');
if(grover_container) {
   const box = await grover_container.boundingBox();
   await page.setViewport({height: box.height, width: box.width});
}

But I totally understand if this is not a direction you want to take the gem, since it creates a dependency on the page content itself to alter the output. I'm also happy to open a PR if this seems worth pursuing. In the meantime, I'll open a PR for the original issue I raised.

...and, of course, thanks for creating this awesome gem. It's been simple to use, has a clean and well-tested code base, and is working perfectly for my need.

@abrom
Copy link
Contributor Author

abrom commented Feb 15, 2020

Most websites are responsive these days?! So many different screensizes to deal with (mobile vs desktop!).

I'm just not seeing a case where this would be reusable. For now I'd suggest it is better suited in a fork

@willkoehler
Copy link
Contributor

That makes sense. I found an (arguably better) solution for my use-case that works with the mainline gem. So it's all good 👍

In the meantime I opened a PR to address the original issue. Thanks again for this awesome gem!

@abrom abrom closed this as completed in #43 Feb 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants