# Goodbye Print to PDF: the last step in an AI deck

> Everyone builds slides with AI now. Sending them is where it falls apart. The four ways printing HTML to PDF breaks, the two-step method that fixes all four, and how to install the skill in Claude and in ChatGPT.

- Source: https://athr21.com/writing/goodbye-print-to-pdf/
- Published: 2026-09-09
- Track: Field notes
- Reading time: 6 minutes
- Language: English
- Author: Aly Zeineldin, Athr21

---

I stopped printing to PDF by hand in June. Not because Cmd+P is hard. Because for about a year I kept sending people a file that was not the thing I had made, and I kept not noticing until someone opened it in front of me.

The deck looked right in the browser. The PDF that landed had a different typeface, a three-column comparison flattened into one long stack, and a white half-page where a section had jumped. I fixed each one by hand, each time, as though it were a fresh accident.

It was not a fresh accident. It is four bugs, they are always the same four, and they have one cause each.

## The four

The font is not your font. Chrome starts printing before the web font has finished downloading, so it falls back to a generic sans. Your brand typeface is in the CSS and absent from the file.

The columns collapse. Chrome's print viewport is narrow. Any `@media (max-width:760px)` rule you wrote for phones fires during printing, so every multi-column grid stacks into one column.

The text comes out heavy or garbled. Chrome embeds glyphs as Type 3 fonts. On screen it looks fine. In Preview and Acrobat it renders thick and smeared, and this happens even when the right font did load.

White gaps open between pages. A tall block that cannot fit the space left on a page jumps whole to the next one and leaves the remainder empty.

None of the four has anything to do with your design being wrong. They are all Chrome doing something reasonable in the wrong context.

## Pick the mode before you touch anything

This is the decision that produces most of the ugly output, and it takes two seconds.

A **deck** is fixed 16:9 slides, one screen each. One slide becomes one page, forced, at 1280x720.

A **document** is a proposal, a report, a one-pager: a vertical page of sections. Content has to flow and fill the pages.

Get this backwards and you get the gaps. The instinct with a document is to keep each section whole, so you write `page-break-inside: avoid` on the section, and a tall section that cannot fit jumps and leaves half a page white. The rule is the opposite: let sections flow across page boundaries, and protect only the small blocks, a card, a table row, a callout, so those never split down the middle.

## The method, both modes

Two steps. The second one sounds wrong until you try it.

One. Print through headless Chrome instead of the print dialogue. Give it a long virtual time budget so the web font actually arrives, and its own profile so it never fights with the Chrome you have open.

```
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
  --headless=new --disable-gpu --no-pdf-header-footer --no-margins \
  --virtual-time-budget=20000 \
  --user-data-dir=/tmp/chrome-pdf-export \
  --print-to-pdf="/abs/path/out.pdf" \
  "file:///abs/path/source.html"
```

Paper size is not a flag. It comes from the `@page { size: A4 }` rule in your CSS. A4 for MENA and Europe, letter for the US.

Two. Rasterise it. Turn every page into a high-resolution image and rebuild the file from those images.

```
pdftoppm -png -r 200 out.pdf page
img2pdf $(ls page-*.png | sort) --pagesize A4 -o final.pdf
```

It sounds like vandalism. The rebuilt file contains no fonts at all, so there is nothing left to render differently. It looks identical in Preview, in Acrobat, in a browser, on a phone, on a machine that has never heard of your typeface. The Type 3 problem cannot happen because there are no fonts to be Type 3.

The trade-off is real: the text is no longer selectable. For a deck or a client document that is a fair price. If you need selectable text, skip the rasterise step and embed the font in the HTML as a base64 data URI instead. You keep the copy-paste and you keep a little of the risk.

Then check it, which takes one command:

```
pdffonts final.pdf     # must list no fonts at all, header row only
```

If that prints a list of fonts, the second step did not run.

## Install it in Claude

A skill is a folder with a `SKILL.md` file in it. No terminal, no clone.

On [the repo page](https://github.com/Alyzein77/html-to-pdf), click the green Code button and choose Download ZIP. In Claude, open Settings, go to Capabilities, and add the ZIP as a skill. That is the install.

After that you do not call it. You say "turn this HTML into a PDF" and it reads the file and picks the mode itself.

## Install it in ChatGPT

Same folder, different door. In the sidebar go to Plugins, open the Skills tab, choose Create, then Upload from your computer, and give it the unzipped folder.

One condition worth knowing before you try: skills are not on the free plan, and which paid plans have them has been moving, so check your own settings rather than my word for it. The folder itself is identical either way, so you are not locked into one company's format.

## What has to be on your machine

Three things, and the first is probably already there.

Google Chrome, used headlessly. Poppler for the page tools, `brew install poppler`. And `img2pdf`, `pip install img2pdf`.

All of it runs on your own machine, which is the condition worth saying out loud: this is desktop work, not something you can do from a phone.

## Where this sits

This is the fifth step in a chain I wrote about when I [closed Canva](/writing/goodbye-canva-branded-decks-without-designing/): a brand file the AI reads first, decks of your own to teach it how you argue, a skill that builds in HTML, a humaniser pass, and then this.

Four of those five make something good. This one makes it sendable. A beautiful HTML deck sitting on your laptop is not a deliverable, and nobody wants a link to a file they cannot open on a phone in a taxi.

I did not get better at exporting. I stopped doing it.
