How to Test a Website’s Print CSS with Screenshots
Emulate print media in Chrome or Playwright, capture stable screenshots, and check paginated output with a separate PDF workflow.
To test print CSS with screenshots, switch the page to print media before capturing it. For a quick manual check, use Chrome DevTools’ Rendering panel and set Emulate CSS media type to print. For repeatable checks, use Playwright: call page.emulateMedia({ media: 'print' }), capture a screenshot, and compare it with a reviewed baseline. Use a PDF as a separate check when you need to inspect page breaks, page size, or pagination.
A screenshot can show whether print-only elements appear and screen-only elements disappear. It does not by itself prove that page breaks, physical print dimensions, or every printer’s output are correct. Pair screenshot comparison with PDF inspection when those details matter.
1. Know what each print check tells you
| Check | Use it for | Output |
|---|---|---|
| Chrome DevTools emulation | Quick visual diagnosis while editing CSS | Live page rendered with print media rules |
| Playwright screenshot | Repeatable visual review or regression checks | PNG or another screenshot format, optionally compared with a baseline |
| Playwright PDF | Pagination, page size, margins, and page breaks | PDF rendered with print CSS |
Chrome documents print media emulation in the Rendering panel. Playwright supports print media emulation and screenshots through its Page API. Its PDF method also uses print CSS, but the result is a PDF and print color defaults can alter colors. Chrome: Emulate CSS media features · Playwright Page API
2. Inspect print styles manually in Chrome DevTools
- Open the page in Chrome and open DevTools.
- Open the Rendering panel. If it is not visible, use the DevTools command menu or panel options to find it.
- Set Emulate CSS media type to print.
- Inspect the page: check visibility, colors, typography, links, images, and layout changes controlled by
@media print. - Edit CSS temporarily in DevTools to isolate a problem, then make the durable change in your project stylesheet.
- Capture a screenshot if you need a visual record. DevTools emulation is a manual inspection workflow; use an automated test runner for baseline assertions.
Common things to inspect include navigation and controls that should disappear, print-only notes that should appear, content width, readable type size, link treatment, and whether important backgrounds or images are missing. Verify each against your own print requirements; there is no universal rule for what every site should hide.
Chrome’s documented workflow is to force print preview mode through the Rendering panel’s Emulate CSS media type control and select print. See Chrome’s instructions.
3. Capture print media with Playwright
The essential order is: navigate, emulate print media, then screenshot. Save the following as print-shot.js after installing Playwright with npm install playwright. Run it with node print-shot.js https://example.com.
const { chromium } = require('playwright');
(async () => {
const url = process.argv[2];
if (!url) throw new Error('Usage: node print-shot.js https://example.com');
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1280, height: 900 } });
await page.goto(url, { waitUntil: 'networkidle', timeout: 60000 });
await page.emulateMedia({ media: 'print' });
await page.screenshot({ path: 'print-view.png', fullPage: true });
console.log('Saved print-view.png');
} finally {
await browser.close();
}
})();
The example uses Chromium and a full-page image. Playwright’s Page API also supports media: 'screen'. For a viewport-only image, remove fullPage: true. Pin the browser and execution environment used for your baseline so later comparisons are meaningful. Playwright Page API
Choose a stable readiness condition
networkidle can be convenient for mostly static pages. Pages with analytics, polling, streaming, or other ongoing network activity may never become idle. In that case, wait for the application’s meaningful content instead, then allow any known layout or font work to finish:
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
await page.locator('main article').waitFor({ state: 'visible', timeout: 15000 });
await page.evaluate(() => document.fonts.ready);
await page.emulateMedia({ media: 'print' });
await page.screenshot({ path: 'print-view.png', fullPage: true });
Replace main article with a selector that identifies the content you actually need to test. If print rules themselves load content or change layout, emulate before waiting for the relevant final state.
4. Add a visual regression assertion
For an ongoing check, use Playwright Test’s screenshot assertion. Install the test runner with npm install -D @playwright/test. Save this as tests/print.spec.js and run npx playwright test:
const { test, expect } = require('@playwright/test');
test('article print layout matches its reviewed baseline', async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 900 });
await page.goto('http://127.0.0.1:3000/article', {
waitUntil: 'domcontentloaded'
});
await page.locator('main article').waitFor({ state: 'visible' });
await page.emulateMedia({ media: 'print' });
await expect(page).toHaveScreenshot('article-print.png', {
fullPage: true,
animations: 'disabled'
});
});
On the first run, Playwright Test creates a reference image. Later runs compare captures against that reference; review and version-control intentional baseline changes. The assertion waits until two consecutive screenshots are identical before comparing. Playwright: Visual comparisons · Playwright PageAssertions
Make baselines useful instead of noisy
- Keep the rendering environment consistent. Browser version, operating system, fonts, settings, hardware, and headless mode can change pixels. Use the same environment for baseline creation and later runs.
- Control variable content. Freeze clocks or test data when appropriate. Playwright supports screenshot-only stylesheets through
stylePathand masks for volatile elements; use them only for content that is genuinely outside the behavior under test. - Choose a difference threshold intentionally. Playwright supports pixel- and ratio-based thresholds. Set one based on reviewed project needs; a permissive threshold can hide regressions.
- Review baseline updates. A passing image comparison only means the new image is within the configured comparison rules. It does not establish semantic correctness or identical results on every physical printer.
- Assert key visibility separately. Check important print-only and screen-only content explicitly as well as reviewing the whole-page image.
Example visibility assertions can make intent explicit:
await expect(page.locator('.print-only')).toBeVisible();
await expect(page.locator('.screen-only')).toBeHidden();
5. Inspect pagination with a PDF
A full-page screenshot is useful for the overall print-media layout, but it is one tall image. To check page breaks, paper dimensions, margins, and paginated output, generate a PDF as a companion artifact:
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('http://127.0.0.1:3000/article', {
waitUntil: 'networkidle', timeout: 60000
});
await page.pdf({ path: 'article-print.pdf', format: 'A4' });
} finally {
await browser.close();
}
})();
page.pdf() renders with print CSS and creates a PDF rather than a screenshot. Its default print color handling can modify colors; if exact colors matter to the generated PDF, Playwright points to the CSS property -webkit-print-color-adjust. Treat the PDF and screenshot as complementary checks. Playwright Page API
6. Check the CSS behaviors your site depends on
- Visibility: Are navigation, interactive controls, and other screen-only elements hidden as intended? Are print-only instructions shown?
- Content completeness: Are headings, code blocks, tables, images, and footnotes present? Does any container clip or conceal content?
- Readable layout: Does the content use the available page width and remain legible when colors and backgrounds change?
- Links and references: Can readers identify destinations if links are printed? Should external URLs be exposed by your design?
- Pagination: Do headings separate from the paragraphs they introduce? Do important blocks split awkwardly? Inspect the PDF because a single screenshot does not show physical page boundaries.
- Dynamic content: Are lazy-loaded images and client-rendered content present before the capture? Wait for app-specific readiness rather than assuming navigation completion guarantees it.
- Responsive assumptions: Print media is distinct from a narrow screen viewport. Test mobile screen layout separately if it is in scope.
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Screenshot looks like the normal website | Print emulation happened after the screenshot, or was never enabled | Call emulateMedia({ media: 'print' }) before capture; in DevTools select print in the Rendering panel. |
| Automated navigation times out on a busy site | networkidle waits for network quiet that the page never reaches |
Use a suitable earlier navigation milestone and wait for a specific content selector or app-ready signal. |
| Fonts or images differ between runs | Capture began before resources or client rendering settled | Wait for visible content and, where relevant, document.fonts.ready; ensure images are loaded before capture. |
| Baseline fails on a different machine | Rendering environment, fonts, browser version, or headless behavior differs | Run baseline and comparison in a consistent pinned environment, then review rather than blindly accepting diffs. |
| Screenshot is unexpectedly very tall or unwieldy | fullPage: true captures the complete document as one image |
Use a viewport screenshot for local layout details, or generate a PDF to inspect page boundaries. |
| Colors in the PDF do not match the screenshot | PDF print color handling can change colors by default | Check whether exact colors are required and review -webkit-print-color-adjust for PDF output. |
| Visual diff reports harmless changes | Dynamic timestamps, animation, ads, or remote content vary | Disable animations, stabilize test data, or mask only the known volatile region; keep meaningful content under assertion. |
| Print-only content remains hidden | Selector specificity, stylesheet ordering, or an incorrect media query | Inspect computed styles while print media is active and verify the element’s matching rules and cascade. |
8. Performance, reliability, and cost
For local development, DevTools is the lowest setup-cost route: it gives immediate feedback without a test harness. Playwright adds installation, browser execution, and baseline maintenance, but makes repeat checks repeatable. Full-page screenshots can use more memory for long pages; capture a targeted viewport or element when that answers the question, and reserve full-page images for checks that need the entire document. There is no universal runtime or cost figure: it depends on page weight, browser environment, CI capacity, and how many pages you capture.
For reliability, run screenshots in a consistent environment, use explicit readiness conditions, and keep baselines reviewed. If printed output is a requirement, keep a PDF inspection step too. A screenshot regression test catches visual changes against a chosen reference; it does not validate every printer or establish that content is semantically correct.
9. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its screenshot API captures a URL; use the call below for a convenient rendered-page screenshot. For a specific print-CSS regression check, your capture workflow must emulate print media before taking the screenshot, as in the Playwright example above. Consult the ScreenshotNeo documentation for API options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up free for 1,000 screenshots a month, no card required.
10. Frequently asked questions
Does a screenshot prove what a printed page will look like?
No. It shows browser rendering under print media rules. Use a PDF to inspect pagination and page setup, and consider physical proofing when printer-specific output matters.
Should I test print CSS in every browser?
Use the browser engines and versions that matter to your users and deployment. Keep each baseline tied to its browser environment; pixel comparisons across different environments can vary.
Why use both screenshot assertions and explicit visibility assertions?
The image catches broad visual changes, while a visibility assertion states a specific requirement in a focused way. Together they make failures easier to interpret.
Can DevTools create automated screenshot baselines?
The documented DevTools workflow is for emulating and inspecting print media. Use a test runner such as Playwright Test when you need repeatable baseline assertions.


