← demos
claude code skill

pdf — HTML to continuous single-page PDF

A Claude Code skill that converts an HTML file into one continuous, single-page PDF sized exactly to its rendered content. Two methods, chosen by page complexity.

name
pdf
description
Convert an HTML file to a continuous single-page PDF. Use when the user wants to generate a PDF from HTML.
allowed-tools
Bash, Read, Edit
argument
[html-file-path]

Choose by page complexity:

1Headless Chrome (preferred)

CHROME="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
SCRATCH=<scratchpad dir>   # work on copies, never the original

# 1. Measure true rendered height: inject a reporter into a COPY, read it via dump-dom
python3 - <<'EOF'
src = open("$FILE").read()
src = src.replace("</body>", "<script>window.addEventListener('load',()=>{setTimeout(()=>{document.title='H:'+document.documentElement.scrollHeight},1500)})</script></body>")
open("$SCRATCH/measure.html","w").write(src)
EOF
H=$("$CHROME" --headless=new --disable-gpu --dump-dom --virtual-time-budget=12000 \
    --window-size=<design_width+~120>,2000 "file://$SCRATCH/measure.html" 2>/dev/null \
    | grep -o '<title>H:[0-9]*' | grep -o '[0-9]*$')

# 2. Into a print COPY, inject @page sized to content (width = the design's fixed width, else 800px):
#    @page { size: <width>px <H+24>px; margin: 0; }
#    @media print { body { -webkit-print-color-adjust: exact; } }

# 3. Print
"$CHROME" --headless=new --disable-gpu --no-pdf-header-footer --virtual-time-budget=15000 \
  --print-to-pdf="<output.pdf>" "file://$SCRATCH/print.html"

Notes:

2weasyprint (simple pages)

  1. Inject @page { size: 800px 200px; margin: 0; }, render with Python weasyprint, count pages → height ≈ pages × 200.
  2. Replace the @page height with the measured total; run weasyprint in.html out.pdf.
  3. If the page uses CSS custom properties, flatten every var(--x) to its literal first (weasyprint crashes on var() in gradients). If it uses calc()-based grids or web fonts, STOP and use Method 1 instead.

weasyprint warnings about box-shadow / print-color-adjust are harmless.

Shared rules

Never edit the source HTML in place — copy to scratchpad, inject, convert.