<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nick</title>
    <description>The latest articles on DEV Community by Nick (@nickpad).</description>
    <link>https://dev.to/nickpad</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F109898%2Fed352be7-c28d-46ee-bd1f-d19bfc6e6a27.png</url>
      <title>DEV Community: Nick</title>
      <link>https://dev.to/nickpad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nickpad"/>
    <language>en</language>
    <item>
      <title>Print CSS basics in 10 minutes</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Thu, 05 Sep 2019 04:01:05 +0000</pubDate>
      <link>https://dev.to/nickpad/print-css-basics-in-10-minutes-41jk</link>
      <guid>https://dev.to/nickpad/print-css-basics-in-10-minutes-41jk</guid>
      <description>&lt;p&gt;This article will teach you everything you need to get started writing CSS for pages that are intended to be printed.&lt;/p&gt;

&lt;p&gt;You might be building a page for your web app that will be converted to PDF. Or, maybe you just want your site's existing pages to look good when a user prints them.&lt;/p&gt;

&lt;h1&gt;
  
  
  The &lt;a class="mentioned-user" href="https://dev.to/media"&gt;@media&lt;/a&gt; rule
&lt;/h1&gt;

&lt;p&gt;If you've done any responsive design, you'll already know about the &lt;code&gt;@media&lt;/code&gt; rule. As well as different screen sizes, &lt;code&gt;@media&lt;/code&gt; also lets you target "print" media. Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* These styles will only be used when the page is printed or saved to PDF. */&lt;/span&gt;
  &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16pt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this rule, you can specify your standard CSS as normal and then add some custom styles that will only be used when printing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Hide related article links when printing. */&lt;/span&gt;
  &lt;span class="nc"&gt;.related-articles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to "zero out" all your standard screen styles and start from&lt;br&gt;
scratch, you can wrap your screen styles in another &lt;code&gt;@media&lt;/code&gt; rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* standard styles here. */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* print styles here. */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Page break properties
&lt;/h1&gt;

&lt;p&gt;To make sure the content flows smoothly across pages, you'll want to control when content gets split between pages. For example, it looks awkward if a large heading appears at the bottom of a page - you want it to start on a new page instead. Similarly, you may want to avoid a table spanning multiple pages if possible.&lt;/p&gt;

&lt;p&gt;You can do this using &lt;code&gt;page-break-before&lt;/code&gt;, &lt;code&gt;page-break-after&lt;/code&gt;, and &lt;code&gt;page-break-inside&lt;/code&gt;. You can set the value for these properties to &lt;code&gt;always&lt;/code&gt; or &lt;code&gt;avoid&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* h1 elements always start on the top of a new page. */&lt;/span&gt;
  &lt;span class="nl"&gt;page-break-before&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="nc"&gt;.city-map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* this section always occupies it's own page or pages. */&lt;/span&gt;
  &lt;span class="nl"&gt;page-break-before&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;page-break-after&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;table&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* tables don't split across pages if possible. */&lt;/span&gt;
  &lt;span class="nl"&gt;page-break-inside&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;avoid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Tip: Repeat table headings
&lt;/h1&gt;

&lt;p&gt;If your document has tables that span multiple pages, it'll be hard to read when printed unless the table headers are repeated at the start of each page. This is pretty easy to accomplish - just use the &lt;code&gt;thead&lt;/code&gt; and &lt;code&gt;tbody&lt;/code&gt; elements in your table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;City&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Population&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Sydney&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;4.627 million (2018)&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When printed, your table will then look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4vea0qxsfl7r6bipxv96.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4vea0qxsfl7r6bipxv96.png" alt="Table with repeated headings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Tip: Adding or removing content
&lt;/h1&gt;

&lt;p&gt;Sometimes you might want to add content that's only shown when printing. For example - you might want to link URLs to be printed. You can do this by using the &lt;code&gt;:after&lt;/code&gt; pseudo-element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;href&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;" ("&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s1"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might also want to hide or show certain elements only when printing. By combining &lt;code&gt;@media&lt;/code&gt; and &lt;code&gt;display&lt;/code&gt; this can be done quite easily.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* hide the watermark on screens. */&lt;/span&gt;
&lt;span class="nc"&gt;.watermark&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* hide the navidation when printing. */&lt;/span&gt;
  &lt;span class="nt"&gt;nav&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hide&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c"&gt;/* show the watermark when printing */&lt;/span&gt;
  &lt;span class="nc"&gt;.watermark&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Tip: Use emulate CSS media for development
&lt;/h1&gt;

&lt;p&gt;To speed up your feedback loop during development, you can set your browser to display print styles. To do this in Chrome on Mac, open developer tools, then use the command-shift-P shortcut for "Run Command" and search for "Emulate CSS print media type".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fid71gkks06xlnuqinwdc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fid71gkks06xlnuqinwdc.png" alt="Emulate CSS media"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Other browsers will have a similar feature in their dev tools.&lt;/p&gt;

&lt;p&gt;Unfortunately to see page breaks you'll need to print to PDF manually each time.&lt;/p&gt;

&lt;h1&gt;
  
  
  Advanced tip: Orphans and widows
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;orphans&lt;/code&gt; and &lt;code&gt;widows&lt;/code&gt; properties control how text in an element is split across pages. Sometimes tweaking these values can improve the readability of your printed document.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* if there aren't at least three lines before the page
     break, move the element to the start of a new page. */&lt;/span&gt;
  &lt;span class="nl"&gt;orphans&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh0x2jtmf8e2qezhirv9h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh0x2jtmf8e2qezhirv9h.png" alt="Orphans example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the left below, &lt;code&gt;orphans&lt;/code&gt; is set to 2, so the second paragraph begins&lt;br&gt;
before the page break. By setting &lt;code&gt;orphans&lt;/code&gt; to 3, as on the right, the&lt;br&gt;
paragraph is forced down to the start of the next page.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;widows&lt;/code&gt; property is the opposite of &lt;code&gt;orphans&lt;/code&gt; - it specifies the minimum number of lines that can be at the start of a new page.&lt;/p&gt;
&lt;h1&gt;
  
  
  Advanced tip: the &lt;a class="mentioned-user" href="https://dev.to/page"&gt;@page&lt;/a&gt; rule
&lt;/h1&gt;

&lt;p&gt;With the &lt;code&gt;@page&lt;/code&gt; rule, you can customise the page margin for specific pages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* No margin on the first page. */&lt;/span&gt;
  &lt;span class="nt"&gt;margin&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@page&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Set a margin on all other pages. */&lt;/span&gt;
  &lt;span class="nt"&gt;margin&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;2&lt;/span&gt;&lt;span class="nt"&gt;cm&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, browser support for this is currently a little limited and you&lt;br&gt;
can only use the &lt;code&gt;:first&lt;/code&gt;, &lt;code&gt;:last&lt;/code&gt;, &lt;code&gt;:left&lt;/code&gt;, &lt;code&gt;:right&lt;/code&gt; and &lt;code&gt;:blank&lt;/code&gt;&lt;br&gt;
pseudo-selectors to select pages.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;You're now familiar with the important properties for print layout that are supported by modern browsers like Chrome, Firefox and Safari.&lt;/p&gt;

&lt;p&gt;Unfortunately support for more advanced print layout features in modern&lt;br&gt;
browsers is generally limited. For example, browsers don't provide a standard way of adding custom header or footer content using CSS. You may want to check out the &lt;a href="https://www.pagedmedia.org/paged-js/" rel="noopener noreferrer"&gt;paged.js project&lt;/a&gt; which offers a polyfill for many of the print layout features browsers are currently missing.&lt;/p&gt;

</description>
      <category>css</category>
      <category>pdf</category>
    </item>
    <item>
      <title>Modern HTML to PDF conversion</title>
      <dc:creator>Nick</dc:creator>
      <pubDate>Fri, 02 Nov 2018 05:32:58 +0000</pubDate>
      <link>https://dev.to/nickpad/modern-html-to-pdf-conversion-31i0</link>
      <guid>https://dev.to/nickpad/modern-html-to-pdf-conversion-31i0</guid>
      <description>&lt;p&gt;Many web apps require some sort of PDF functionality. And as a web developers, we already know one great way to lay out documents — HTML!&lt;/p&gt;

&lt;p&gt;But there’s a confusing array of options available for converting HTML to PDF. In this article I’m going to consider the pros and cons of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Established tools like &lt;a href="https://wkhtmltopdf.org/" rel="noopener noreferrer"&gt;wkhtmltopdf&lt;/a&gt; that have been in use for years&lt;/li&gt;
&lt;li&gt;Google Chrome in “headless” mode&lt;/li&gt;
&lt;li&gt;Specialist software built specifically for converting HTML to PDF&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I should state upfront that I originally wrote this for the &lt;a href="https://www.paperplane.app/?utm_source=devto&amp;amp;utm_campaign=convert-html-to-pdf-2018" rel="noopener noreferrer"&gt;Paperplane&lt;/a&gt; blog. Paperplane is a cloud API I've created for generating PDFs but it’s just one of many options available. I’ve tried to present a fair and accurate comparison of the trade offs involved in each of the options presented in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tried and tested approaches
&lt;/h2&gt;

&lt;p&gt;Until 2017, there were two common ways to convert HTML to PDF. The first was to use &lt;a href="https://wkhtmltopdf.org/" rel="noopener noreferrer"&gt;wkhtmltopdf&lt;/a&gt; — an open source command line tool specifically designed for the task. A second alternative was &lt;a href="http://phantomjs.org/" rel="noopener noreferrer"&gt;PhantomJS&lt;/a&gt;, an open source “headless” web browser which can be controlled with JavaScript.&lt;/p&gt;

&lt;p&gt;Although these tools have served many people extremely well, they do have some downsides. Support for the latest HTML5 and JavaScript features lags a long way behind the modern browsers we’re used to such as Chrome, Firefox or Safari. Some users of wkhtmltopdf &lt;a href="https://blog.rebased.pl/2018/07/12/wkhtmltopdf-considered-harmful.html" rel="noopener noreferrer"&gt;report issues with inconsistent rendering&lt;/a&gt; and have to tweak settings using trial and error to achieve the desired output. PhantomJS offers fewer options for configuring PDF output than wkhtmltopdf and development on the project was suspended in March 2018.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chrome Headless
&lt;/h2&gt;

&lt;p&gt;Things changed in April 2017 with the &lt;a href="https://developers.google.com/web/updates/2017/04/headless-chrome" rel="noopener noreferrer"&gt;release of Google Chrome 59&lt;/a&gt; which included a “headless” mode. In conjunction with &lt;a href="https://chromedevtools.github.io/devtools-protocol/" rel="noopener noreferrer"&gt;Chrome’s “devtools” API&lt;/a&gt;, headless mode allows you to use Chrome in a server environment and script it to perform tasks — like creating PDFs!&lt;/p&gt;

&lt;p&gt;You can get started by &lt;a href="https://developers.google.com/web/updates/2017/04/headless-chrome#create_a_pdf_dom" rel="noopener noreferrer"&gt;using the “print-to-pdf” command line option&lt;/a&gt;, but for more control over the PDF you’ll need to communicate with Chrome’s devtools API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Controlling Chrome with Puppeteer
&lt;/h2&gt;

&lt;p&gt;Since the release of headless mode, a strong ecosystem of tools has emerged for interacting with the devtools API. Foremost amongst these is “&lt;a href="https://github.com/GoogleChrome/puppeteer" rel="noopener noreferrer"&gt;Puppeteer&lt;/a&gt;”, a &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; library that’s been built by the Google Chrome team themselves. You could use Puppeteer to script the browser to perform countless tasks, but we’ll be focusing on how it can be used to create PDFs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Puppeteer with Chrome on your own server
&lt;/h3&gt;

&lt;p&gt;When you install Puppeteer on your server or in your development environment, &lt;a href="https://github.com/GoogleChrome/puppeteer#installation" rel="noopener noreferrer"&gt;it will automatically download it’s own copy of Chrome for you&lt;/a&gt;! Surprisingly simple, right? Bear in mind though that a Chrome install can be up to 300MB, and running Chrome has the potential to use a significant amount of your server’s resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Puppeteer via browserless.io
&lt;/h3&gt;

&lt;p&gt;If you don’t want to install Chrome on your own infrastructure, but do like the idea of using Puppeteer then it’s worth checking out a service called &lt;a href="http://browserless.io/" rel="noopener noreferrer"&gt;browserless.io&lt;/a&gt;. It lets you connect to a browser running in the cloud, freeing you from the server administration involved in installing, running and updating Chrome yourself. You can also run up to 20 browser sessions in parallel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Puppeteer via Google Cloud Functions
&lt;/h3&gt;

&lt;p&gt;One interesting new option is the ability to run headless Chrome on Google Cloud’s “serverless” platform — Cloud Functions. This feature was added to Cloud Functions in August 2018 and should provide a low-cost and highly scalable way of generating PDFs. &lt;a href="https://cloud.google.com/blog/products/gcp/introducing-headless-chrome-support-in-cloud-functions-and-app-engine" rel="noopener noreferrer"&gt;Google’s announcement post&lt;/a&gt; has a good walk-through that explains how to set it all up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating your own PDF microservice
&lt;/h2&gt;

&lt;p&gt;If you want to generate PDFs on your own servers, but keep all PDF-related concerns out of your main application, you should check out &lt;a href="https://github.com/esbenp/pdf-bot" rel="noopener noreferrer"&gt;pdf-bot&lt;/a&gt;. It’s a Node.js microservice that can receive URLs via it’s API, add them to a queue, and then notify you via webhooks when the URL has been converted to PDF. It also supports storing your PDF files on Amazon S3.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating PDFs using a cloud API
&lt;/h2&gt;

&lt;p&gt;If you don’t mind paying a small amount to outsource your PDF infrastructure and focus on more important features, consider using a cloud API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.paperplane.app/?utm_source=devto&amp;amp;utm_campaign=convert-html-to-pdf-2018" rel="noopener noreferrer"&gt;Paperplane&lt;/a&gt; is one option here — you send URLs to it’s API and it takes care of converting them to PDF using Chrome. The finished PDFs are uploaded to your own Amazon S3 storage. You can set options like page size and include headers and footers just as you would if you were using Puppeteer. Finally, if you have lots of documents to create, Paperplane can generate up to 20 PDFs in parallel. For more information, you can check out the &lt;a href="https://www.paperplane.app/?utm_source=devto&amp;amp;utm_campaign=convert-html-to-pdf-2018" rel="noopener noreferrer"&gt;full list of features&lt;/a&gt; or the &lt;a href="https://docs.paperplane.app/?utm_source=devto&amp;amp;utm_campaign=convert-html-to-pdf-2018" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fine-grained control — advanced typesetting features
&lt;/h2&gt;

&lt;p&gt;If Chrome isn’t able to produce the PDF output you need, then there are a few commercial software packages you might want to investigate. These all have great support for &lt;a href="https://drafts.csswg.org/css-page-3/" rel="noopener noreferrer"&gt;CSS paged media&lt;/a&gt; — a CSS module for controlling print or PDF output. CSS paged media support in Chrome is reasonable but currently incomplete in some areas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.princexml.com/" rel="noopener noreferrer"&gt;PrinceXML&lt;/a&gt; is capable of creating extremely well-formatted output (check out the &lt;a href="https://www.princexml.com/samples/" rel="noopener noreferrer"&gt;samples&lt;/a&gt; on their website) but at a steep price of $3800 for a 1-server licence. However, if you require some of the features that only it can offer, such as automatic hyphenation, footnotes or print crop marks, then the cost may be worthwhile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docraptor.com/" rel="noopener noreferrer"&gt;Docraptor&lt;/a&gt; is a cloud API backed by PrinceXML that lets you get started with PrinceXML at a much lower price point.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.pdfreactor.com/" rel="noopener noreferrer"&gt;PDFreactor&lt;/a&gt; is a competitor to PrinceXML with a similar price tag and a similar focus on producing print-quality PDF output.&lt;/p&gt;

&lt;p&gt;Finally, &lt;a href="https://weasyprint.org/" rel="noopener noreferrer"&gt;weasyprint&lt;/a&gt; stands out in this category as the only free open-source option. It has &lt;a href="https://weasyprint.readthedocs.io/en/stable/features.html" rel="noopener noreferrer"&gt;better support for paged media&lt;/a&gt; than Chrome but lacks a JavaScript engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing the options
&lt;/h2&gt;

&lt;p&gt;To summarise, I’ve attempted to grade the different PDF rendering engines according to three criteria — support for modern web standards, support for JavaScript, and support for paged media and other advanced typesetting features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhxs6v7zuyk0rza3t4kxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhxs6v7zuyk0rza3t4kxf.png" alt="Comparison table" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope this helps you choose the right option for your project! If you've got this far let me know what you're using in the comments 😀.&lt;/p&gt;

</description>
      <category>pdf</category>
      <category>chrome</category>
    </item>
  </channel>
</rss>
