ScreenshotNeo

BlogHow-to

How to Add Custom CSS Before Percy Takes a Screenshot

Add CSS to one Percy snapshot, configure it for every snapshot, or prepare the page in your test before capture. Includes examples and troubleshooting.

By the ScreenshotNeo team4 October 20265 min read

To add custom CSS before Percy takes a screenshot, either pass a percyCSS string to one snapshot or set snapshot.percy-css in .percy.yml for project-wide Percy styling. If the application page itself must change before capture, apply CSS or make DOM changes in your test before calling the Percy snapshot function.

Use Percy-specific CSS for capture-only adjustments, such as hiding a timestamp or chat widget that makes screenshots unstable. Use test-side page preparation when you need the browser page itself to change before Percy captures it. Keep elements that are part of the layout or behavior under test visible.

1. Add CSS to a single Percy snapshot

Pass the percyCSS option alongside the snapshot name. This scopes the override to that capture:

await percySnapshot('Home page', {
  percyCSS: 'iframe { display: none; }'
});

For multiple rules, use a template literal:

await percySnapshot('Home page', {
  percyCSS: `
    .live-chat,
    .rotating-promo {
      display: none !important;
    }

    *,
    *::before,
    *::after {
      animation: none !important;
      transition: none !important;
    }
  `
});

Replace the example selectors with selectors from your page. The !important declarations help override existing page rules. Disabling motion can make visual captures more consistent when animation is the source of variation.

2. Apply Percy CSS to every snapshot

To share the same CSS across snapshots, put it in the project’s .percy.yml configuration:

version: 1
snapshot:
  percy-css: |
    iframe {
      display: none;
    }
    .live-chat {
      visibility: hidden;
    }

Use display: none when the element should take up no space. Use visibility: hidden when preserving its layout space matters. Check the project’s Percy configuration and installed SDK documentation if the setting is not being applied.

3. Change the page in your test before capture

Sometimes the capture needs a real page change rather than a Percy-only visual override. In that case, apply the stylesheet or make the DOM change in the test before the snapshot call. The following browser-side example injects a style element; adapt the browser access to the test framework and Percy integration you use:

await page.addStyleTag({
  content: `
    .live-chat,
    .rotating-promo {
      display: none !important;
    }
  `
});

await percySnapshot('Home page');

Here, page.addStyleTag is a Playwright page method. Other test frameworks expose page or browser APIs differently. The key order is the same: wait until the page is ready, apply the change, then call Percy’s snapshot function.

4. Choose the right CSS scope

Approach Scope Use it when
percyCSS snapshot option One snapshot A single page or state needs a capture-specific override.
snapshot.percy-css in .percy.yml Project snapshots The same visual cleanup applies consistently throughout the project.
CSS or DOM changes in the test The page under test The application state itself must be prepared before capture.

What is safe to hide?

Common sources of screenshot variability include live chat, notification badges, counters, rotating banners, and ads. Hide them only if they are outside the behavior or layout the test is intended to verify. If the test checks a chat widget, banner, or ad placement, hiding it would mask a regression.

For data-driven content, control the test data when possible so the page remains representative while producing repeatable captures. CSS is useful for visual noise, but it does not make changing application data deterministic.

5. Troubleshoot CSS that does not appear in the screenshot

Symptom Likely cause Fix
The element remains visible. The selector does not match the rendered element, or another rule overrides it. Inspect the rendered DOM, use a more specific selector, and try !important for the override.
CSS works in one capture but not another. The override is configured per snapshot, or the snapshots use different markup. Move shared rules to snapshot.percy-css and confirm the selector matches each page.
The test-side style has no effect. The style is injected after the snapshot call, before navigation finishes, or into the wrong page/frame. Wait for the relevant page state, apply the style to the page being captured, then take the snapshot.
Hidden content leaves an awkward blank gap. visibility: hidden hides paint but preserves layout space. Use display: none if removing the element’s layout space is intended.
The screenshot still changes between runs. Other content is dynamic, or animations and transitions continue during capture. Disable relevant motion, stabilize test data, and identify any remaining changing elements.
Percy rejects or ignores the option. The installed SDK or configuration may not support the syntax being used. Check the documentation for the installed Percy SDK and validate the YAML structure and option spelling.

Percy’s September 2019 announcement demonstrated both per-snapshot CSS and global configuration, and stated that the feature required @percy/agent v0.13.0 or newer at that time. Treat that version note as historical, not as a current compatibility guarantee; check your installed SDK’s documentation. See Percy’s Percy Specific CSS changelog entry and its guidance on reducing false positives in visual testing.

6. Performance, reliability, and maintenance

  • Keep overrides narrow. A selector limited to known unstable components is easier to maintain than a broad rule that hides large parts of the page.
  • Disable only relevant motion. Turning off animations and transitions can reduce variability, but avoid suppressing motion that the visual test is meant to cover.
  • Prefer stable test data. CSS can hide a changing element; controlled data makes the rest of the page repeatable too.
  • Revisit global rules. A project-wide selector can silently affect new pages. Review shared CSS when page markup or test coverage changes.
  • Keep preparation before capture. In test code, apply styles after the target page is available and before invoking the snapshot function.

Or skip the browser setup

For a website screenshot without setting up a browser capture flow, ScreenshotNeo returns a screenshot from one GET request. The API supports custom CSS and JavaScript, alongside full-page and element captures. For API parameters and options, see the ScreenshotNeo documentation.

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  --data-urlencode format=webp \
  --data-urlencode css='body { background: white; }' \
  -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={
        "access_key": "YOUR_API_KEY",
        "url": "https://stripe.com",
        "format": "webp",
        "css": "body { background: white; }",
    },
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://stripe.com',
  format: 'webp',
  css: 'body { background: white; }'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', new Uint8Array(await res.arrayBuffer()));

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000 screenshots.

Get 1,000 free screenshots a month with no card.

FAQ

Does Percy CSS change my live website?

Percy-specific snapshot CSS is intended to style the capture. Test-side changes run in the browser page used by your test, so keep them within the test flow.

Should I use per-snapshot CSS or global CSS?

Use per-snapshot CSS for a one-off exception and global configuration when the same rule should apply throughout the project.

Can CSS make a visual test fully deterministic?

No. It can suppress visual noise such as motion or unstable widgets, but changing content and test data may need separate control.