How can I change paper size in headless Chrome --print-to-pdf

20,123

Solution 1

The page size could be set in inches/mm. I haven't tested with a size in pixels. Here is a set of CSS rules which did the trick for me:

@page {
  margin: 0;
  padding: 0;
  size: 5in 6.5in;
}

My exact case is rendering svg-to-pdf, not html; For svg, you may also need to add width and height attributes to <svg> tag:

<svg width="5in" height="6.5in" ...>

That's all! Output PDF won't have margins, and will preserve the desired size - 5"x6.5" in my case.

Solution 2

You can run headless chrome from Node environment.

Then you would be able to pass additional parameters to printToPdf function including pageWidth and pageHeight.

Solution 3

Page size apparently can now be "almost" accurately controlled without using the debug interface.

The following is a method of creating a PDF with nearly the exact dimensions of its contents using headless chrome.

<head>
    <style>
      html, body {
        width:  fit-content;
        height: fit-content;
        margin:  0px;
        padding: 0px;
      }
     </style>

     <style id=page_style>
      @page { size: 100px 100px ; margin : 0px }
     </style>

</head>

This prepares for making the pdf to fit the page, but will not be right, since the page size has been set to an arbitrary value of 100x100.

After the document has been rendered, the following is used to set the page size correctly at the bottom of the page:

<script>
window.onload(fixpage);

function fixpage() {

     renderBlock = document.getElementsByTagName("html")[0];
     renderBlockInfo = window.getComputedStyle(renderBlock)

     // fix chrome page bug
     fixHeight = parseInt(renderBlockInfo.height) + 1 + "px"   

     pageCss = `@page { size: \${renderBlockInfo.width} \${fixHeight} ; margin:0;}`
     document.getElementById("page_style").innerHTML = pageCss
}
</script>

This approach eliminates the header/footer and deals with a numerical issue with pixel conversion to pdf.

One more thing

Chrome currently has a bug with the calculation of absolute height of a div when you use the CSS

line-height: normal; 

This will make the page calculation too short and lead to an extra pdf page being generated. You can fix this using:

line-height: unset; 

Throughout your CSS. You won't get an accurate height without it!

Solution 4

There was a patch created sometime ago that enables page sizing configuration https://codereview.chromium.org/2829973002/

It is now closed and available in the unstable version of chrome, so you can use it as you suggested @page { size: A4 }.

I tested, it works on the unstable build I have installed (Google Chrome 61.0.3141.7 dev). I am not sure, though, how to check when it will be available in the stable build ...

Solution 5

Note: after going through the comments in atomrc's answer, I thought about adding this as an answer to be more clear.

You can't change the page size right now unless using the devtools protocol.

This is a bug in headless Chrome. The @page size CSS rule is not understood correctly in headless mode, as this user describes it well on the chromium bug tracker:

Desktop Chrome does support @page at-rules for size and margins, and will set the sheet dimensions according to the size property.

It appears that Headless Chrome does parse @page as well to some extent, but behaves differently than the desktop version: If you specify @page {size}, headless seems to change the dimensions of the page box (essentially, the print area), and not the sheet, which always remains US Letter sized. However, it does rotate the sheet if you specify {size: landscape}.

Share:
20,123
Crazy Yoghurt
Author by

Crazy Yoghurt

Updated on July 11, 2020

Comments

  • Crazy Yoghurt
    Crazy Yoghurt almost 4 years

    I am using headless Chrome to export html documents to pdf

    google-chrome --headless --disable-gpu --print-to-pdf='output_path' 'url'
    

    How can I change paper size in generated pdf?

    I have control on both Chrome parameters and html.

    I always get US Letter.

    There are no documented command-line options for this.

    I've tried setting CSS: @page {size: A4;}. No effect in headless mode, but works when I hit Ctrl+P in normal mode (option to choose paper size for Save as pdf disappears, exported pdf has A4 page size).

    I've tried this on Chrome versions 59, 60 and 61 on Ubuntu 16.04.

  • Crazy Yoghurt
    Crazy Yoghurt almost 7 years
    Thank you Dimitry. I am aware of this option, but it causes additional problems: 1. Chrome instance accepts only one debugging connection. I'd have to spawn multiple instances on multiple ports for each instance of my service. Not so cool. 2. Synchronisation with events (onLoad etc.) is additional layer of complexity. Basically I would need to write a wrapping program running one Chrome instance, which would abstract page-loading, printing etc. Also not so cool. That's why I wanted to use single Chrome instance per single job, automatically closing after it's done, no remote debugging. Simpler
  • Crazy Yoghurt
    Crazy Yoghurt almost 7 years
    That doesn't work. I've installed Chrome 61.0.3153.4 and set @page { size: A4 } in css. That makes no difference. Have you been able to obtain different sizes of paper this way? Anyhow, change that you've linked is not really connected with this problem. Look here: codereview.chromium.org/2829973002/patch/1/10010, params are brutally hard-coded when using shell --print-to-pdf option. It's more connected with @Dimitry Leonov's answer, as it gives you controll while using debugging api.
  • atomrc
    atomrc almost 7 years
    Oh weird, it seems to work on my machine. Here are 2 different generation I just made with headless chrome. The first is with @page { size: A4; } and the second with A3. The output is not the same as you can see imgur.com/QaQQQ8R imgur.com/CYpMopU. That said, the red part is supposed to have a size of 210mm / 297mm so I am not sure why there is a extra margin on the side ...
  • atomrc
    atomrc almost 7 years
    About the patch link I sent you, someone from the Chromium team sent me this link when I asked about page size configuration for headless chrome bugs.chromium.org/p/chromium/issues/detail?id=603559#c30. So I though this would be relevant to you too, but unfortunately I have to admit I am not really able to understand what is going on in this patch :/
  • Crazy Yoghurt
    Crazy Yoghurt almost 7 years
    You're right, output may not be the same. The case is: there are 3 different sizes: paper, page and body. You have changed page size, leaving paper and body untouched. Chrome squeezes larger page to the same paper size, so your body gets visually smaller. It looks similar to printing on larger paper size, but you may check pdf properties and you'll see that it stayed the same (at least in my case)
  • atomrc
    atomrc almost 7 years
    I am not really aware of those three different sizes. You seem to know a lot more than I do about PDF, so I guess I cannot help you, sorry :/ BTW How are the results I showed you different from what you expect? Does that mean I need to look, somehow, in the metadata of the generated PDF?
  • Crazy Yoghurt
    Crazy Yoghurt almost 7 years
    To check pdf paper size, you should open it in Acrobat Reader and right click on any page. In description tab there's page size in inches (Acrobat Reader DC 2017.009 on macOS). Or use any other pdf viewer you have :)
  • omegastripes
    omegastripes almost 5 years
    I just put the style tag into head of my HTML (without CData), set size in mm, and it works.
  • Avael Kross
    Avael Kross almost 5 years
    Yes, for HTML it's true - just put a style tag into <head>. My case is for svg rendering, so I need CDATA. I should state it more clearly in my answer.