Full page screenshots are like testing the entire house when you only renovated the kitchen. If the living room wallpaper has a scratch, your test fails even though you never touched it. Element-level screenshots focus on one component. Smaller image. Faster comparison. Fewer false positives.
import { test, expect } from '@playwright/test';
test.describe('Banking Portal Components', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/banking');
await page.waitForLoadState('networkidle');
});
test('navigation bar', async ({ page }) => {
const nav = page.getByRole('navigation');
await expect(nav).toHaveScreenshot('nav-bar.png');
});
test('account summary card', async ({ page }) => {
const card = page.getByTestId('account-summary');
await expect(card).toHaveScreenshot('account-card.png', {
mask: [page.getByTestId('live-balance')],
});
});
test('transaction table', async ({ page }) => {
const table = page.getByRole('table');
await expect(table).toHaveScreenshot('transaction-table.png', {
mask: [page.locator('td:nth-child(1)')], // mask date column
});
});
test('footer', async ({ page }) => {
const footer = page.getByRole('contentinfo');
await expect(footer).toHaveScreenshot('footer.png');
});
});import { test, expect } from '@playwright/test';
test.describe('Login Button States', () => {
test('default state', async ({ page }) => {
await page.goto('/banking/login');
const button = page.getByRole('button', { name: 'Login' });
await expect(button).toHaveScreenshot('login-btn-default.png');
});
test('hover state', async ({ page }) => {
await page.goto('/banking/login');
const button = page.getByRole('button', { name: 'Login' });
await button.hover();
await expect(button).toHaveScreenshot('login-btn-hover.png');
});
test('focused state', async ({ page }) => {
await page.goto('/banking/login');
const button = page.getByRole('button', { name: 'Login' });
await button.focus();
await expect(button).toHaveScreenshot('login-btn-focused.png');
});
test('disabled state', async ({ page }) => {
await page.goto('/banking/login');
// Click login without filling fields -- button might show disabled style
const button = page.getByRole('button', { name: 'Login' });
await expect(button).toHaveScreenshot('login-btn-disabled.png');
});
});| Use Case | Element Screenshot | Full Page Screenshot |
|---|---|---|
| Shared component (nav, footer) | Yes | No -- changes to other parts cause false failures |
| Landing page layout | No | Yes -- you care about overall composition |
| Design system components | Yes -- one per state (default, hover, active, disabled) | No |
| After a targeted CSS fix | Yes -- screenshot the fixed component | Also yes -- verify nothing else broke |
| Smoke test for a page | No | Yes -- quick check that page renders |
Element screenshots are faster, more stable, and easier to debug. Use full page screenshots for layout validation. Use element screenshots for component validation. Most teams end up with 80% element tests and 20% full page tests.
Make sure the element is fully visible and not clipped by overflow: hidden on a parent. If the element is partially hidden, the screenshot captures only the visible portion, which can cause inconsistent baselines.
Key Point: Element screenshots test one component in isolation. Smaller images, faster comparisons, fewer false positives. Use them for shared components and state variations.