Thoughts and learnings in my journey through all things technology. Developer operations, software development, server administration and anything else that I decide should be written.

Tags


Simple PDF Generation with Phantom.js

23rd August 2014

Overview

At a previous job I was pleased to have come into contact with PhantomJS.

PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.

We had a challenge to attempt to build out PDF's of presentation decks that would push the bar on most browsers performance as well as taking positioning to an extreme.

PhantomJS allowed us to quite simply build out PDF's without having to have too much thought vs. having to sit and monkey around for weeks with older items such as wkhtmltopdf. While those tools worked great in the early days, PhantomJS having a foundation of webkit makes it operate like our normal browser environment.

Generating the PDF

  1. Download and Install PhantomJS utilizing a binary.

  2. Create the PDF generator. In my case we'll target a URL:

    var page = require('webpage').create(),
        system = require('system'),
        address,
        output;
    
    
    if (system.args.length < 3 || system.args.length > 5) {
        console.log('Usage: pdf.js URL filename');
        phantom.exit(1);
    }
    
    
    address = system.args[1];
    output = system.args[2];
    
    
    page.paperSize = {
        format: 'Letter',
        orientation: 'Landscape',
        border: '0'
    };
    
    
    page.open(address, function() {
        window.setTimeout(function() {
            page.render(output);
            phantom.exit();
        }, 1500);
    });
    
  3. Let's do a quick test with google:

    phantomjs pdf.js http://www.google.com google.pdf
    

Some minor details

One thing to note is there are a vast amount of options. You will most certainly want to read the documentation on them. But breifly we're utilizing 0 border and no margins so we can get a full page print out.

Secondly, you'll notice that we have a setTimeout before we actually render out the page. This is so that any JavaScript may have time to apply itself before we actually render the PDF.

CSS and Printing

There is some care that you will need to tend to when you want to create your own PDF's. There are gotchas and items that you may want to look into.

  1. Ensure the stylesheets you want to print have a media type of: all or print. This is very important! If you do not see your background colors or oddities from the main display it means you missed one of these options.

  2. Using CSS zoom for PDF is great; if you are attempting to get a full page print out without the margins. Otherwise you can look at phantom's zooming options.

  3. Make pages meaningful by using page-break-after.

  4. Force background images and colors: -webkit-print-color-adjust: exact

  5. Fonts, damn fonts. Fonts can be quite tricky when attempting to print. Webfonts will work the majority of the time but you may find that the characters are off. In this case; install them onto your operating system of choice.

Conclusion

PhantomJS is a great tool, I've had great luck with it in generating out PDFs. However, it is not the only thing that PhantomJS can do. For instance the pdf.js script can be utilized to save it in an image by just stating a different file extension.

If you're not using PhantomJS for PDF generation yet; I hope that this article will convince you to do so. If not the article then maybe the small example!

I am a VP of engineering for a small start up. I have over a decade of experience in engineering, database administration, server administration and management.

View Comments