1 / 3 · Book 10 · AI-Powered Visual Comparison · drill: interview Q&A⊞ allnext →Get the book →
1.6Stabilizing Screenshots for Comparison
Dynamic content is the enemy of visual regression testing. Before capturing, stabilize the page:
async function stabilizeForScreenshot(page) {
await page.evaluate(() => {
// 1. Hide dynamic content
const dynamicSelectors = [
'[data-testid="timestamp"]',
'[data-testid="avatar"]',
'[data-testid="live-counter"]',
'[data-testid="ad-slot"]',
];
dynamicSelectors.forEach(sel => {
document.querySelectorAll(sel).forEach(
el => (el as HTMLElement).style.visibility = 'hidden'
);
});
// 2. Disable all animations and transitions
const style = document.createElement('style');
style.textContent = `
*, *::before, *::after {
animation-duration: 0s !important;
animation-delay: 0s !important;
transition-duration: 0s !important;
transition-delay: 0s !important;
}
`;
document.head.appendChild(style);
// 3. Wait for all images to load
return Promise.all(
Array.from(document.images)
.filter(img => !img.complete)
.map(img => new Promise(resolve => {
img.onload = resolve;
img.onerror = resolve;
}))
);
});
// 4. Wait for web fonts to load
await page.waitForFunction(() => document.fonts.ready);
}
Pro Tip: Always stabilize before capturing. Dynamic content like timestamps, avatars, live counters, and advertisements are the number one source of false positives in visual regression testing. Hide them with
visibility: hiddenrather thandisplay: noneso that they still occupy layout space and do not cause layout shifts.
Common Mistake: Using
display: noneto hide dynamic content. This removes the element from layout flow, causing surrounding elements to shift position and triggering additional false positives. Usevisibility: hiddeninstead -- it makes the element invisible but preserves its space in the layout.