The weird things that break when you screenshot a page at the wrong viewport

Most screenshot tools default to 1280×800 or whatever the developer felt like hardcoding. That works until it doesn't.

I was generating thumbnails for a client's portfolio site last month. Everything looked great in the preview — clean grid, nice spacing, images loaded. Then someone opened the actual screenshots and half the cards were stacked vertically with text overlapping. The grid used a CSS breakpoint at 1200px. My viewport was 1180px. Off by 80 pixels.

The annoying part is that nothing "failed." The screenshot captured exactly what the browser rendered. It just rendered the wrong layout.

Viewport isn't just width

Height matters too, in ways people don't expect. Sticky headers, fixed footers, intersection observers that trigger animations on scroll — all of these behave differently depending on the viewport height. I've seen lazy-loaded images come back blank because the viewport was too short and the images were below the fold. The browser never triggered the load.

And then there's device pixel ratio. A screenshot at 1x DPR looks muddy on retina displays. Bump it to 2x and suddenly your 1280px-wide capture is actually 2560 pixels. File sizes double. Processing time goes up. If you're storing thousands of these, that adds up fast.

The mobile mess

Mobile viewports are their own disaster. Setting width to 375 doesn't give you an iPhone screenshot — it gives you a desktop browser squeezed to 375 pixels. Real mobile rendering needs a proper user agent string, touch event support, and sometimes a completely different CSS path.

I've watched people spend hours debugging why their "mobile screenshots" looked wrong before realizing the site was serving the desktop version because the user agent said Chrome on macOS.

Even this isn't perfect. Some sites check or use hover media queries. You can fake some of it with Puppeteer's device emulation presets, but edge cases will always slip through.

Responsive design testing is where this gets real

If you need screenshots across breakpoints — say 320, 768, 1024, 1440, 1920 — you're running the same page five times. Each one might load different assets, trigger different JS, render a different layout. The page at 320px might not even have the same DOM structure as the one at 1920px.

Batching helps, but you need to actually wait for each viewport to finish rendering before capturing. I used to just set the viewport and immediately screenshot. Worked 80% of the time. The other 20% caught layout mid-reflow, half-loaded webfonts, or images still decoding.

Now I wait for plus a short delay after resize. Slower, but the results are actually usable.

What I learned

Three viewport-related rules I follow now:

  • Always set viewport explicitly. Never trust the default. Even headless Chrome's default has changed between versions.
  • Match DPR to your use case. Thumbnails? 1x is fine. Visual QA? 2x minimum. Don't just crank it to 3x everywhere unless you want to burn through storage.
  • Test your test. Screenshot your own screenshot setup at each breakpoint before running it against real pages. Catches the dumb stuff early.

The viewport seems like a minor detail until it isn't. Eighty pixels cost me about four hours of debugging and a confused client. Could've been worse — at least the screenshots were obviously wrong instead of subtly wrong.