<?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: Hannah Whitfield</title>
    <description>The latest articles on DEV Community by Hannah Whitfield (@hannahjwhitfield).</description>
    <link>https://dev.to/hannahjwhitfield</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3995024%2F9cdfc171-bc98-4b42-9824-3a620c954a24.jpg</url>
      <title>DEV Community: Hannah Whitfield</title>
      <link>https://dev.to/hannahjwhitfield</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hannahjwhitfield"/>
    <language>en</language>
    <item>
      <title>Generating Print-Ready PDFs in a Browser Is Harder Than It Looks</title>
      <dc:creator>Hannah Whitfield</dc:creator>
      <pubDate>Fri, 24 Jul 2026 19:21:41 +0000</pubDate>
      <link>https://dev.to/hannahjwhitfield/generating-print-ready-pdfs-in-a-browser-is-harder-than-it-looks-25g3</link>
      <guid>https://dev.to/hannahjwhitfield/generating-print-ready-pdfs-in-a-browser-is-harder-than-it-looks-25g3</guid>
      <description>&lt;p&gt;"Export to PDF" sounds like a solved problem until the output has to go to an actual printer and come back as a physical book. Screen PDFs and print PDFs are different artefacts with different requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  RGB is not CMYK
&lt;/h2&gt;

&lt;p&gt;Browsers work in RGB. Printers work in CMYK. The conversion is lossy and not symmetric — saturated RGB colours, particularly bright blues and greens, have no CMYK equivalent and come back visibly duller.&lt;/p&gt;

&lt;p&gt;Nothing in the browser warns you. The proof looks right on screen and wrong on paper, which is an expensive way to discover the problem.&lt;/p&gt;

&lt;p&gt;Practical mitigation: design within a CMYK-safe palette from the start rather than converting at the end. Muted colours survive the round trip; neon does not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bleed and trim
&lt;/h2&gt;

&lt;p&gt;Print requires content to extend past the trim line — typically 3mm on each edge — so that cutting tolerance does not leave white slivers. A "210×297mm" PDF is wrong for print; you need 216×303mm with trim marks.&lt;/p&gt;

&lt;p&gt;CSS gets you part of the way:&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="nl"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;216mm&lt;/span&gt; &lt;span class="m"&gt;303mm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c"&gt;/* A4 + 3mm bleed each side */&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;0&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;But &lt;code&gt;@page&lt;/code&gt; support is uneven and bleed marks generally are not something the browser will draw for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Image resolution is the most common rejection
&lt;/h2&gt;

&lt;p&gt;Screen images are typically 72-96 DPI. Print needs 300 DPI. An image looking crisp in the browser is roughly a quarter of the resolution a printer wants, and print services reject or flag these.&lt;/p&gt;

&lt;p&gt;Worth validating at upload — compute effective DPI from the intrinsic pixel dimensions against the placed physical size and warn immediately, rather than at export when the user has already done the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pagination is the genuinely hard part
&lt;/h2&gt;

&lt;p&gt;Reflowable HTML has no concept of a page. Getting a recipe to not break across a page boundary means measuring rendered content and making layout decisions, which the browser will not do for you.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;break-inside: avoid&lt;/code&gt; helps for simple blocks and is not sufficient for real layout control. What actually worked: render content off-screen, measure real heights, then assign blocks to pages in code — essentially reimplementing pagination rather than asking CSS to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fonts must be embedded
&lt;/h2&gt;

&lt;p&gt;An unembedded font substitutes at the print shop and your careful typography becomes Helvetica. Whatever generates the PDF must embed subsets — and the font licence has to permit embedding, which not all do.&lt;/p&gt;

&lt;p&gt;I deal with all of this at &lt;a href="https://getcookpress.com" rel="noopener noreferrer"&gt;Cook Press&lt;/a&gt; — recipes in, Etsy-ready hardcover out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveat
&lt;/h2&gt;

&lt;p&gt;If the output is only ever going to be read on screen, ignore most of this. These constraints exist because a physical printing press is on the other end, and they are pure overhead otherwise.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>css</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
