Lazy content prints, with no option to set. Without a scroll option (neither ScrollTo nor ScrollThrough), a page's IntersectionObserver reports every element it observes visible, once, wherever it sits on the page. So what a page loads as it comes into view, lazy pictures, charts drawn when they are reached, items its scripts add, is loaded and printed: the whole page is in the PDF. Chrome reports only what is in its window, so with Puppeteer such a page prints its first screen unless a script scrolls it first.
Some pages want real scrolling: a list that loads more each time its bottom comes into view, effects that follow the scroll, a page opened at a section. Four options scroll the window before printing, as a user would before pressing Print, or print a part of the page. With a scroll option set, Weblitz reports real intersections with the window, as Chrome does.
ScrollThrough: scroll from the top to the end, a window height at a time, so what loads on the way is printed (200 steps at most).
ScrollTo: scroll to "top", "bottom", an element (a CSS selector) or a length, once the scripts have settled; the page's scroll events and IntersectionObserver callbacks see it. A scroll timeline on the page's own scroll prints at its start, scrolled or not, as Chrome prints it.
ScrollStepWait: the virtual time each scroll gives the page to react (0.5 s by default, 0 to 60 s).
Region: print a part of the document (HtmlPrintRegion), from the scroll position, a length or an element, for a height; laid out on pages as a whole document is.
Scrolling alone never crops: the PDF holds the whole document from its top, as Chrome's print of a scrolled page does. Only Region leaves parts out.
The examples below show both: the infinite list prints twenty orders by default, as its observer reports its bottom once, and all sixty with ScrollThrough.
Lists that load as you scroll
An infinite list loads its next ten orders each time its bottom comes into view. Without a scroll option, Weblitz's IntersectionObserver reports the bottom visible once, so the PDF holds twenty; ScrollThrough scrolls the window down a window height at a time, each step waiting ScrollStepWait of virtual time, so the list loads to its end and all sixty are printed.
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>A list that loads as you scroll</title>
<style>
body { font: 11pt/1.4 Arial, sans-serif; margin: 0; }
li { padding: 2.2mm 3mm; min-height: 24mm; box-sizing: border-box; border-bottom: 1px solid #e5e7eb; }
li:nth-child(odd) { background: #f8fafc; }
#more { padding: 3mm; color: #6b7280; font-style: italic; }
</style></head>
<body>
<h1>Orders, loaded 10 at a time as you scroll</h1>
<ol id="list"></ol>
<p id="more">Scroll for more…</p>
<script>
// An infinite list as sites write it: the next ten orders load when the bottom comes into view, up to 60
let loaded = 0;
const list = document.getElementById('list');
function loadMore() {
for (let i = 0; i < 10 && loaded < 60; i++) {
loaded++;
const li = document.createElement('li');
li.textContent = `Order #${1000 + loaded}: ${['Frankfurt', 'Lyon', 'Milano', 'Basel', 'Gent'][loaded % 5]}, ${(loaded * 37) % 900 + 100} EUR`;
list.append(li);
}
if (loaded >= 60) document.getElementById('more').textContent = 'All 60 orders loaded.';
}
loadMore();
new IntersectionObserver((entries) => { if (entries.some(e => e.isIntersecting)) setTimeout(loadMore, 100); })
.observe(document.getElementById('more'));
</script>
</body></html>
Info scriptsRan: The page's scripts ran (884 ms of virtual time, 40 tasks; 0 canvases drawn).
Scrolling to a section first
ScrollTo scrolls the window before printing, as a user would before pressing Print: the page's scroll events and IntersectionObserver callbacks see it (here the sections that went off screen, and scrollY). A scroll timeline on the page's own scroll prints at its start either way, as Chrome prints it. The PDF still holds the whole document from its top.
Info scriptsRan: The page's scripts ran (50 ms of virtual time, 6 tasks; 0 canvases drawn).
Printing a part of the page
Region prints a part of the document, from a start (the scroll position, a length, an element) for a height; what lies above and below is left out, and the part is laid out on pages as a whole document is.