toolkit

Screenshots · Playbook

Lazy-load handling (reference)

Full-page screenshots of modern sites fail naively because content loads on scroll. viewvee handles this in three layers, all on by default for full-page captures:

  1. Auto-scroll (--no-scroll to disable): steps top→bottom in viewport-sized increments so IntersectionObserver lazy-loaders and loading="lazy" images fire, then returns to top. Bounded (hard cap ~50000px + height-stall guard) so infinite-scroll feeds can’t loop forever.

  2. Freeze animations (--no-freeze to disable): injects CSS that zeroes animation/transition durations and forces scroll-reveal libraries (AOS [data-aos], wow.js .wow, animate.css .animated, generic .fade-in/.reveal) to their visible end-state (opacity:1; transform:none). Without this, elements that start at opacity:0 until scrolled into view screenshot as blank boxes.

  3. Wait-for-images: after scrolling, waits (bounded 5s) until every <img> reports complete && naturalWidth > 0, so freshly-triggered lazy images finish decoding before the shot. Best-effort — broken/off-screen images that never resolve don’t block the capture.

Verifying lazy-load actually worked

Heuristic: a working lazy-load capture is tall and multi-hundred-KB to multi-MB. Compare on vs off:

npm run viewvee -- https://site.com -d desktop -o /tmp/on            # default
npm run viewvee -- https://site.com -d desktop -o /tmp/off --no-scroll --no-freeze

If /tmp/on/desktop.png is meaningfully larger/taller than /tmp/off/desktop.png, lazy-load pulled in real content. If they’re the same, the site simply has no lazy content.

Real example (example.org desktop): 3.8 MB with defaults but blanks in an early build → 5.4 MB once wait-for-images + freeze were added; every gallery/icon/portrait filled in.

When to reach for --settle

Very heavy sites (large galleries, video posters, third-party widgets) occasionally need more time than the 5s image wait. Add --settle 2000 (or more) to pause after scroll before capture.