đź“‹ Table of Contents
The "Double Header" Problem
You've just written a Puppeteer script to take a fullPage: true screenshot. You open the file,
and... what's this? The navigation bar appears repeatedly throughout the image, like a glitch in a video
game.
This happens because modern websites often use position: fixed or position: sticky
for headers. When the browser synthesizes a full-page screenshot by scrolling and stitching images together,
these fixed elements get captured in every frame.
Solution 1: CSS Injection
The cleanest way to fix this is to inject a small snippet of CSS before taking the screenshot. We want to change fixed elements to absolute, or hide them entirely if they aren't needed for the context.
/* Hide sticky headers */
header, .sticky, .fixed-top {
position: absolute !important;
top: 0 !important;
}
/* Or hide aggressive popups */
.cookie-banner, .modal {
display: none !important;
}
In Playwright, you can inject this easily:
await page.addStyleTag({
content: 'header { position: absolute !important; }'
});
Solution 2: JavaScript Cleanup
Sometimes you don't know the class names ahead of time. In that case, you can use a brute-force JavaScript approach to find all fixed headers and un-fix them.
await page.evaluate(() => {
const elements = document.querySelectorAll('*');
for (const el of elements) {
const style = window.getComputedStyle(el);
if (style.position === 'fixed' || style.position === 'sticky') {
el.style.position = 'absolute';
}
}
});
Handling Lazy Loading
Another common issue is empty white spaces at the bottom of the page. This is usually caused by images that only load when they come into the viewport (Lazy Loading).
To fix this, you must simulate a human user scrolling down the page before you take the screenshot.
async function autoScroll(page){
await page.evaluate(async () => {
await new Promise((resolve) => {
let totalHeight = 0;
const distance = 100;
const timer = setInterval(() => {
const scrollHeight = document.body.scrollHeight;
window.scrollBy(0, distance);
totalHeight += distance;
if(totalHeight >= scrollHeight - window.innerHeight){
clearInterval(timer);
resolve();
}
}, 100);
});
});
}
The Easy Way
Handling all these edge cases—sticky headers, cookie banners, lazy loading images, infinite scrolls—is a maintenance nightmare.
SnapAPI handles all of this automatically. Our engine detects fixed elements and handles the stitching logic so you get a clean, perfect image every time.
Stop Fighting with CSS
Get perfect full-page screenshots with a single API call.
Try SnapAPI Free →