Make a Printable PDF Edition of a Web Treatment Without Losing Content
Make a Printable PDF Edition of a Web Treatment Without Losing Content
A browser treatment is built to fill a window that changes size. A PDF is built to sit on a page that doesn't. Those are different jobs, and if the print route is left to chance, the page wins — usually by dropping what didn't fit, quietly, in a way that looks like a finished document.
The PDF you want is not a picture of whatever was on screen when someone pressed the print shortcut. It's a second edition of the same treatment: laid out for finite pages, carrying the same content, honest about what it can't carry, and labeled so a reader can tell which version of the web document it represents.
Three moves get you there. Inventory the treatment's actual content before you touch a stylesheet, so you know what "complete" means. Build the print layout by releasing screen-only constraints rather than shrinking them. Then export the thing and read it page by page, because a print stylesheet can't promise that a panel, caption, or qualification survived — only the pages can show you that.
Establish the content the static edition must contain
Start with a list, not a layout. Go through the treatment and write down what it actually says: the logline, the location, the casting note, the shot list, the two frames with their captions, the previz description, the note about the permit. Then, next to each item, write down where it lives in the document.
That second column is where the trouble shows up, because a surprising amount of a treatment lives somewhere you can't see. Some of it is in a tab that isn't selected. Some is in a scrolling box, scrolled to the top while four-fifths of it sits below the fold. Some is in an expandable panel nobody opened. And some of it, in the worst case, doesn't exist in the document at all until a click builds it.
Distinguish controls from content. The row of links in the header is a control; it reveals nothing and can go, or be converted into a printed contents list. A "Cast" button is also a control — but the paragraph the button reveals is content, and it's the kind that matters most, because it's the kind that goes missing without anyone noticing. Same for the caption under a frame and the parenthetical qualifier ("subject to permit," "second crossing subject to weather") that sits in a footnote-looking note nobody reads until they need it.
Here's a sample to work with. It's written for this article and hasn't been exported anywhere; treat it as a construction, not a report of something that happened.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Harbor Line — Treatment, rev. C</title>
<link rel="stylesheet" href="treatment.css">
</head>
<body>
<header>
<h1>Harbor Line</h1>
<p class="revision">Treatment rev. C — matches web edition of 14 September</p>
<nav aria-label="Sections">
<a href="#opening">Opening</a>
<a href="#look">Look</a>
<a href="#sound">Sound</a>
</nav>
</header>
<section id="opening">
<h2>Opening</h2>
<p>Cold open on the ferry deck, 5:40 a.m. The camera holds the rail.</p>
<div class="tabs">
<button role="tab" aria-selected="true" aria-controls="panel-route">Route</button>
<button role="tab" aria-selected="false" aria-controls="panel-cast">Cast</button>
<div id="panel-route" role="tabpanel">
<p>Two crossings, filmed back to back, same deck.</p>
</div>
<div id="panel-cast" role="tabpanel" hidden>
<p>Three deckhands. None speak. The youngest appears on the
6 a.m. crossing only.</p>
</div>
</div>
<div class="shotlist"> <!-- .shotlist { height: 340px; overflow-y: auto } -->
<h3>Shot list</h3>
<ol> <!-- forty rows of notes; roughly eight are visible at a time --> </ol>
</div>
<figure>
<img src="frame-014.jpg" alt="Deck rail at first light, mist over the water">
<figcaption>Frame 14. The light changes twice in this setup; we keep
the second pass.</figcaption>
</figure>
<figure>
<video controls preload="metadata" src="previz.mp4" poster="previz.jpg"></video>
<figcaption>Previz. The ferry turnaround, 22 seconds.</figcaption>
</figure>
</section>
</body>
</html>
Four known problems are sitting in it. The Cast paragraph is hidden. The shot list is trapped in a fixed-height scrolling box. The frame and its caption can be split by a page break. And the previz is a video, which is content the PDF cannot play. There's a fifth, milder one: the nav row.
Before you fix any of them, decide what the print edition is. Give it a name, a revision, and the web edition it was taken from — the sample's revision line is doing that work. Not "treatment.pdf" sitting in a downloads folder with no way to tell whether it predates the version the client saw.
Build a print layout from meaningful source order
Add a print stylesheet properly: either a second <link> with media="print", or one file with an @media print block. Both are documented, both work, and the second is usually less to maintain.
Then declare the page itself, because page size and margins determine what counts as "too tall" later:
@page { size: Letter; margin: 18mm 16mm; }
Choose Letter or A4 deliberately. MDN's printing guide documents that @page can set page dimensions and margins for paper and PDF output, and it's the one place where the layout gets a boundary instead of an endless scroll. Changing from A4 to Letter changes your pagination, so the choice belongs in the edition's identity, not in whoever's print dialog happens to be open.
Now release the screen constraints rather than shrinking them.
@media print {
nav { display: none; }
.shotlist { height: auto; overflow: visible; }
.tabs [role="tabpanel"], [hidden] { display: block; }
img, video { max-width: 100%; height: auto; }
.sticky-sidebar { position: static; }
}
That block is a starting point, not a finished one, and it's worth understanding why. The fixed height and the overflow-y: auto are what clip the shot list: the browser only ever shows a 340-pixel window onto forty rows, and printing doesn't open that window. Releasing both properties makes all forty rows available. Sticky positioning has the same flavour of problem — an element pinned to the viewport has no viewport to pin to on paper. And a hidden panel needs to be made visible before the export is taken, which is why the reveal has to be a stylesheet rule, not a script that runs after the print dialog has already grabbed its snapshot.
That last point deserves its own sentence, because it's the difference between a five-minute fix and a source rewrite. If the panel is in the markup and merely hidden — by the hidden attribute, by display: none, by an off-canvas class — a print rule can bring it back. If the tab widget builds the panel's contents on click, nothing in a stylesheet can resurrect them, because at print time they were never in the document. Browsers do document a print lifecycle event you can hook to expand things before printing, and it's a reasonable belt to wear. It's not the plan. The plan is that all the treatment's content exists in the source, and the screen's job is to hide parts of it.
One more thing the print layout has to fix: the tab labels are content headings that happen to be wearing a control's clothing. "Cast" is the name of the casting note. In print, the button row either disappears — leaving an orphan paragraph with no label — or you promote the labels to real headings so the printed page reads Cast followed by the note. Same words, different job.
What you must not do is shrink the desktop canvas until it fits. A 55 percent scale-to-fit prints the same missing Cast paragraph, just smaller, with body text at a size nobody will read. A screenshot is worse: it captures exactly one tab and exactly one scroll position, which is the least representative artifact the treatment can produce — and, because it looks like a complete page, it's the one most likely to get sent on.
MDN's printing documentation is careful about its own scope here, and so should you be. It documents print-specific styles, page dimensions, and print events as mechanisms. It doesn't promise that your hidden content, your links, your fonts, or your document structure will survive the trip. That's not a gap in the documentation. That's the part your own export has to answer.
Control breaks without pretending every block will fit
Some things belong together, and page breaks are indifferent to which. Set the relationships you care about:
@media print {
h2, h3 { break-after: avoid; }
figure { break-inside: avoid; }
table { break-inside: avoid; }
}
A heading that lands at the bottom of a page with its explanation overleaf is a reading failure you can prevent. So is a caption orphaned onto the next page while its frame sits above. break-after: avoid and break-inside: avoid are the tools for exactly those cases.
Then accept their limit. The CSS Fragmentation specification says that content which can't be divided — replaced elements like images and video, and boxes whose overflow is constrained — is treated as monolithic, and that break-avoidance can be relaxed when content genuinely cannot fit. Translated into your shot list: if you never release the fixed height, the scrolling box is monolithic, and its overflow is not going to be turned into extra pages. It just isn't there. And once you have released the height, forty rows of shot notes are taller than a Letter page, so break-inside: avoid on that list is a wish, not a plan. The spec's own answer is that the avoidance rule gives way.
So let the long list break, and do it deliberately. The break will land somewhere in the middle of a page boundary, and the reader arriving at the top of page four will see rows with no visible context. Give the list internal subheadings — "Deck," "Cabin," "Shore" — so a page always starts under a label rather than mid-thought. Chunking the source is a more reliable way to keep a long sequence legible than any break rule, because it survives whatever the browser decides to do.
Same reasoning for an oversized frame. A portrait still that's taller than the page area will not be saved by break-inside: avoid. Either give it a page mostly to itself and accept the whitespace, or make a print-specific crop. What you should not do is leave it to a rule that the specification explicitly allows to be ignored.
Replace interactions and inspect the real PDF
The previz is the clearest case of content that a static edition has to translate rather than reproduce. Three substitutions, in order of quality:
- A labeled frame sequence — say, three stills at the head, middle, and end — with a sentence describing what changes between them: "The hull swings from screen left to screen right across 22 seconds; the last four seconds hold on the water."
- A statement, in the PDF, of what the static edition cannot show. The timing is the content here, and a reader of the PDF should know they're missing it rather than infer that the shot is static.
- The playback route, as a real link and as visible text. The same documentation that covers print styles doesn't promise that links survive export, so print the URL where it can be read and copy-pasted, and keep the clickable version as a convenience. This is the one place where the PDF can reach back out to the web edition — and the only honest way it can.
A poster frame with the word "video" under it is not a substitute. It carries the caption's information and none of the motion's.
Then export it, through a route you can name afterwards. Whichever browser you use, use its Print → Save as PDF path (or its export command, if it has one), write down the browser, the page size, the margin setting, and whether headers, footers, and background graphics were on — because those settings change what lands in the file, and "it printed wrong" is not a diagnosis. Save two things: the uncorrected export first, before you add print CSS, as a control that shows you what your document actually loses. That control is more useful than any general advice, including this article's. Then export the corrected edition.
Read the corrected PDF page by page against your inventory. Not a scroll-through — page by page, with a pen.
- Is the Cast paragraph there, and in the right place relative to the Route paragraph?
- Does the shot list end at row forty, or at row twelve where the old fixed height cut it off?
- Are all the captions still attached to their frames?
- Did the revision line and the web-edition date make it into the file?
- Is anything at a size a person would actually read?
- Do the links resolve, and does the visible URL match the link?
- Did the oversized element get handled, or did it vanish?
Order matters here. Missing content is a different class of failure from an ugly page. Polish the way the pages break only after you've reconciled the content, because good typography on the wrong content is the most convincing kind of wrong.
Finally, keep the two editions distinguishable. Name the file so it says what it is — treatment, revision, print, page size — and say inside it that this is a static reading edition of a named web version. It is not press-ready: no imposition, no colour separation, no printer certification. It is also not an accessible PDF simply because a browser produced it; the reading structure of the exported file is a separate job with its own checks, and it's worth doing separately rather than assuming the export handled it.
The end state is modest and specific: a PDF whose every section can be traced back to the treatment it came from, whose moving parts have been replaced with labeled stills and a stated limitation, and whose file says which web edition it represents. When you have that, you can start worrying about whether the caption sits a little low on page six.
Frequently asked questions
Why isn't a screenshot or scale-to-fit print of a web treatment enough?
A screenshot captures exactly one tab and one scroll position, which is the least representative artifact the treatment can produce, and because it looks complete it is the one most likely to be sent on. A 55 percent scale-to-fit prints the same missing content, just smaller, with body text at a size nobody will read. The PDF should be a second edition of the same treatment, laid out for finite pages, carrying the same content, honest about what it cannot carry, and labeled with the web edition it represents.
How should print CSS handle hidden panels, fixed-height scrollers, and sticky elements?
Release the screen constraints rather than shrinking them. A print block can hide nav, set a fixed-height shot list to height auto and overflow visible so all rows are available, reveal tab panels or hidden elements with display block, set img and video to max-width 100% and height auto, and make sticky positioning static. If a panel is in the markup and merely hidden, a print rule can bring it back. If a tab widget builds the panel's contents on click, no stylesheet can resurrect them because they were never in the document at print time. A print lifecycle event can be a belt to wear, but the plan is that all content exists in the source.
What should happen to navigation and tab labels in print?
A row of header links is a control that reveals nothing and can go or become a printed contents list. Tab labels are content headings wearing a control's clothing: 'Cast' is the name of the casting note. In print the button row either disappears and leaves an orphan paragraph with no label, or the labels are promoted to real headings so the page reads 'Cast' followed by the note. Same words, different job.
How should a video previz be represented in a static PDF?
Translate it rather than reproduce it. A labeled frame sequence, say three stills at head, middle, and end, with a sentence describing what changes between them, is the first option. Second, state in the PDF what the static edition cannot show, because timing is content and a reader should know they are missing it rather than infer the shot is static. Third, give the playback route as a real link and as visible text, since links are not promised to survive export. A poster frame with the word 'video' under it carries the caption's information and none of the motion's.
What checks should happen after exporting the PDF?
Read the corrected PDF page by page against an inventory, with a pen, not a scroll-through. Check whether the Cast paragraph is present and in the right place, whether the shot list ends at row forty or at row twelve where a fixed height cut it off, whether captions remain attached to frames, whether the revision line and web-edition date made it in, whether anything is at a readable size, whether links resolve and the visible URL matches, and whether an oversized element was handled or vanished. Reconcile content before polishing page breaks. Record the export route and settings, save the uncorrected export first as a control, and keep the file named so the static edition and its web source are distinguishable.