ThisCalculator

Everyday

Playwright Full Page Screenshots with Custom CSS

Updated · Standard formula, shown below

Average pace 5.00 min/km
Average speed
12.00 km/h
Result
Finish time
50 min
You entered
Distance
10 km
You entered

Playwright Full Page Screenshots with Custom CSS

To take a full-page screenshot with custom CSS in Playwright, you capture the page with page.screenshot({ fullPage: true }) after injecting your styles via page.addStyleTag(). This lets you override backgrounds, hide elements, or force a specific viewport width before the screenshot is taken.

Formula

Pace (min/km) = Finish time (min) ÷ Distance (km). Speed (km/h) = Distance (km) ÷ (Finish time (min) ÷ 60).

Worked Example

With a finish time of 50 minutes and a distance of 10 km: pace = 50 ÷ 10 = 5.00 min/km. Speed = 10 ÷ (50 ÷ 60) = 10 ÷ 0.8333 = 12.00 km/h.

Why Full-Page Screenshots Need Custom CSS

Playwright’s built-in fullPage: true captures the entire scrollable height of the page, but it does not automatically adjust the layout. Many sites have fixed headers, sticky footers, or background colors that only cover the viewport. Custom CSS injected before the screenshot solves these issues by:

  • Removing fixed elements that repeat on every scroll segment (e.g., position: fixed headers).
  • Setting a uniform background color to avoid white gaps when the page is taller than the viewport.
  • Forcing a specific width (e.g., 1280px) so the full-page capture matches a desired design.
  • Hiding pop-ups, cookie banners, or lazy-loaded images that would otherwise break the capture.

How to Inject CSS Before the Screenshot

The process is straightforward in both Node.js and Python. Here is a Node.js example:

  1. Launch a browser and create a page.
  2. Navigate to the target URL.
  3. Call page.addStyleTag({ content: '...' }) with your custom CSS.
  4. Wait for any network requests or fonts to settle (e.g., page.waitForLoadState('networkidle')).
  5. Call page.screenshot({ path: 'full.png', fullPage: true }).

In Python, the equivalent is page.add_style_tag(content='...') and page.screenshot(full_page=True). The key is that the CSS is applied before the screenshot, so the browser renders the page with your overrides.

Common Problems and Solutions

Several issues can occur when capturing full-page screenshots:

  • Fixed elements appear multiple times: Use CSS like header, footer { position: static !important; } to make them flow naturally.
  • Background is white or transparent: Set html { background: #fff; } to fill the entire height.
  • Images lazy-load: Scroll through the page before screenshotting or use page.evaluate() to force loading.
  • Viewport width issues: Set a specific viewport with page.setViewportSize({ width: 1280, height: 800 }) before navigating.
  • Animations not finished: Wait for animations to complete by using page.waitForTimeout(500) or better, wait for a specific element to be stable.

Choosing Between Full-Page and Element Screenshots

Full-page screenshots are ideal for documenting entire web pages, creating visual regression tests, or sharing a complete view of a long article. Element screenshots (using locator.screenshot()) are better when you only need a specific component, like a chart or a form, and want to avoid capturing unrelated content. For full-page captures, you often need custom CSS to normalize the layout; for element captures, you usually don’t, because the element is already isolated.

Costs and Performance Considerations

Taking full-page screenshots can be resource-intensive, especially for very long pages. The browser must render the entire page, and the resulting image can be several megabytes. In CI/CD pipelines, this can slow down tests and increase memory usage. To mitigate, you can:

  • Limit the maximum height captured (e.g., by clipping the page with CSS).
  • Use type: 'jpeg' with a quality setting to reduce file size.
  • Capture only after the network is idle to avoid missing resources.
  • Run captures in parallel but with a pool of browsers to avoid memory spikes.

There is no monetary cost for using Playwright itself, but the infrastructure (e.g., cloud CI) may charge based on execution time.

Alternatives to Custom CSS

If you cannot inject CSS, consider these alternatives:

  • Use Playwright’s page.emulateMedia() to change color scheme or media type, which can affect backgrounds.
  • Modify the page content via page.evaluate() to remove elements or change styles directly.
  • Use a separate browser profile with a user stylesheet (though this is less portable).
  • Take multiple viewport screenshots and stitch them manually, but this is more complex and error-prone.

Frequently Asked Questions

Can I use custom CSS without affecting the actual page?

Yes, the CSS injected via addStyleTag is only applied to the page in the browser instance; it does not modify the server-side files. It disappears when the page is closed.

Why does my full-page screenshot have a white bottom section?

This usually happens because the body or html element has a background that only covers the viewport height. Set html { background: #fff; } (or any color) to fill the entire scrollable area.

How do I capture a full-page screenshot of a page that uses infinite scroll?

Infinite scroll pages don’t have a fixed height. You need to scroll programmatically to load all content, then capture. Use page.evaluate() to scroll to the bottom repeatedly until the height stops changing, then take the screenshot.

Can I set the viewport width for the screenshot without changing the browser window?

Yes, use page.setViewportSize({ width: 1920, height: 1080 }) before navigating. This changes the viewport for that page only, not the browser window size.

Does fullPage: true work with clip?

No, clip and fullPage are mutually exclusive. If you need a specific region of the full page, you must either capture the full page and crop the image later, or use element screenshots.

How do I wait for fonts to load before screenshotting?

Use document.fonts.ready via page.evaluate() to wait for all fonts to load. For example: await page.evaluate(() => document.fonts.ready).

Related

Formula used
in t | Finish time | min | 50 | 0
in d | Distance | km | 10 | 0
out pace | Average pace | min/km | t / d | 2
out speed | Average speed | km/h | d / (t / 60) | 2

Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.