How to render (in pdf) responsive pages in PhantomJS

2.4k Views Asked by At

I'm wondering how to render responsive pages using PhantomJS in pdf format. I have tried so many responsive pages and found that it is printing the pdf using the print css. So, if the page includes the print css OR screen only css it will render the pdf same as we found via print command preview (Ctrl + p).

Is there any way OR script by which i can get the pdf as I'm seeing them on web browser?

Attaching the file when i tried to get the pdf from http://getbootstrap.com/examples/jumbotron/.

Also the main issue is not responsive designes, the issue is print css applied over them.

example pdf

2

There are 2 best solutions below

2
On

This is quite tricky since there is no option to tell PhantomJS to use the screen when rendering as PDF.

You would need to

  1. load all the linked stylesheets that contain a print block with __utils__.sendAJAX,
  2. remove @media print block (this is quite hard with regex because you need to look out for balanced braces, but relatively easy with plain JS),
  3. maybe you even need to rename @media screen to @media print,
  4. remove the linked stylesheet from the document and
  5. add a style element which has the manipulated stylesheet inside (preferable in the same place as the previous stylesheet) to the DOM.

Your page won't look good, because you usually have page breaks and the like with pdf. Also, page width and viewport width are quite hard to get right. Changing the page width doesn't change the viewport, so it won't be the proper responsive that would have with a pixel perfect png. But that is only a solution if you don't need selectable text.

3
On

jorupp came up with a javascript solution in this gist. It essentially let's you "lock" all the media queries in the document's stylesheets to whatever applies presently, before changing to print mode.

In case the link ever disappears, here's the code:

function process(rule) { 
 if(rule.cssRules) { 
  for(var i=rule.cssRules.length-1; i>=0; i--) { 
   process(rule.cssRules[i]);
  }
 }
 if(rule.type == CSSRule.MEDIA_RULE) {
  if(window.matchMedia(rule.media.mediaText).matches) {
   rule.media.mediaText = "all";
  } else {
   rule.media.mediaText = "not all";
  }
 }
 return rule;
}    
for(var i=0; i<document.styleSheets.length; i++) { 
 process(document.styleSheets[i]);
}