ScreenshotNeo

BlogHow-to

How to Disable CSS Animations in Visual Regression Screenshots

Use Playwright’s screenshot option to stop CSS animations, transitions, and Web Animations from changing visual regression captures.

By the ScreenshotNeo team4 October 20266 min read

For Playwright Test screenshot assertions, pass animations: 'disabled' to toHaveScreenshot(). It stops CSS animations, CSS transitions, and Web Animations during capture. Finite animations are fast-forwarded to completion; infinite animations are canceled to their initial state for the screenshot and then played again afterward. This is designed to make a screenshot assertion less dependent on the exact frame at which capture happens.

import { test, expect } from '@playwright/test';

test('page renders without animation interference', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveScreenshot('homepage.png', {
    animations: 'disabled',
  });
});

Check the API documentation for your installed Playwright version when adopting screenshot options; behavior and documented defaults are versioned. See the Playwright PageAssertions API.

1. Disable animation for one screenshot

Set the option on the assertion that should capture a stable visual state:

await expect(page).toHaveScreenshot('dashboard.png', {
  animations: 'disabled',
});

This is a good default for visual regression snapshots when motion itself is not what the test is checking. The option handles CSS animations, CSS transitions, and Web Animations as documented by Playwright. It does not mean Playwright simply removes every animation rule: finite effects are fast-forwarded to their end, while infinite effects are temporarily canceled at their initial state.

2. Set a project-wide screenshot default

If most screenshots in the project should be captured without motion, set the option in playwright.config.ts:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  expect: {
    toHaveScreenshot: {
      animations: 'disabled',
    },
  },
});

A per-assertion option is useful when only some pages need it or when a test intentionally captures animation behavior. Keep the project default aligned with what the snapshots are intended to represent.

3. Choose the right motion control

Goal Approach What it means
Get a repeatable screenshot without motion changing the captured frame animations: 'disabled' Playwright applies its screenshot handling to CSS animations, transitions, and Web Animations.
Test the page as a visitor whose device requests less motion reducedMotion: 'reduce' in the browser context Emulates the prefers-reduced-motion: reduce media feature so the site’s own CSS and behavior can respond.
Filter or override volatile page styling for a capture Screenshot style option Applies custom screenshot CSS; inspect the result because a style override can change the intended visual state.

These controls serve different purposes. Reduced-motion emulation tests the page’s response to a user preference; it is not a substitute for the screenshot assertion option when the goal is to force a stable capture. The prefers-reduced-motion feature has reduce and no-preference values. A site may reduce or replace non-essential movement rather than removing every animation. See Playwright emulation documentation and MDN’s prefers-reduced-motion reference.

For example, application CSS can honor the preference:

@media (prefers-reduced-motion: reduce) {
  .animated-element {
    animation: none;
  }
}

4. Use a custom screenshot stylesheet when needed

Playwright’s screenshot APIs accept a stylesheet string or path. A broad override you can try is:

const screenshotStyle = `
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
`;

await expect(page).toHaveScreenshot('homepage.png', {
  style: screenshotStyle,
});

Use this as a custom implementation pattern, not a universal guarantee. CSS cascade interactions can change the page’s final appearance, and application JavaScript may continue updating the DOM or styles independently. Review the capture to confirm it shows the intended state. Playwright documents screenshot styles as a way to filter dynamic or volatile page content; relevant screenshot options can pierce Shadow DOM and apply to inner frames.

5. Stabilize the rest of the page

Disabling animation does not make every page deterministic. Playwright’s screenshot assertion waits until two consecutive page screenshots match before comparing the result, and screenshot styles can also hide or change dynamic content. A live clock, rotating content, randomized data, asynchronous images, or network-driven updates can still make snapshots vary.

  1. Navigate to the page and wait for the app-specific state your test needs.
  2. Disable animation on the screenshot assertion or configure a project-wide default.
  3. Use a screenshot style only for volatile content that is intentionally irrelevant to the assertion.
  4. Keep browser, operating system, settings, hardware, power source, and headless mode consistent across baseline creation and comparison.
  5. Inspect changed snapshots to distinguish a real UI change from environmental or data variation.

Playwright lists host operating system, browser version, settings, hardware, power source, and headless mode among factors that can affect screenshots. See its visual comparisons guidance.

6. Troubleshooting

Symptom Likely cause Fix
The screenshot still changes between runs Volatile content or environment differences remain after animation handling. Wait for the required app state, stabilize or filter dynamic content, and keep the capture environment consistent.
An animation appears at an unexpected point Finite and infinite animations are treated differently; disabling does not simply delete all animation declarations. Check whether the effect is finite or infinite and inspect the captured state. Use a custom style only when its resulting layout is the intended one.
The custom CSS does not stop a visible update Application JavaScript may be changing the DOM or styles independently of CSS animation and transition rules. Synchronize the test with the application state or add an app-specific test hook; a CSS override cannot guarantee control over every script-driven update.
Reduced-motion emulation did not make the page static The page may reduce or replace non-essential motion instead of removing all movement, or its CSS may not respond to the preference. Use animations: 'disabled' for stable screenshot capture. Keep reduced-motion emulation for testing the user preference behavior.
The configured option is rejected or has no effect The installed Playwright version may differ from the documentation or the option may be set at the wrong level. Check the installed version and the matching PageAssertions API; use the assertion-level example to confirm placement.

7. Performance, reliability, and cost

The option is part of the screenshot assertion API, so it avoids adding a separate animation-disabling package or a hand-written page-wide rule for the common case. The available sources do not provide a benchmark for its runtime cost or a quantified reliability improvement. It cannot guarantee deterministic output if the page data, application state, browser, or host environment changes.

For continuous integration, keep snapshot generation and comparison on a consistent browser and operating system, and review baseline updates as code changes. When screenshot volume or browser setup is a concern, a screenshot API can capture a URL without maintaining browser automation infrastructure.

Or skip the browser setup

For a URL-based capture, ScreenshotNeo provides a screenshot API and MCP server for developers. Its clean-shot flow accepts cookie and consent banners like a visitor 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, timeouts, failed loads, and cache hits cost nothing, and responses indicate the page verdict and billing status in headers. Its MCP server exposes screenshot and page information tools for Claude, Cursor, and other MCP clients.

See the ScreenshotNeo API documentation. One GET request returns an image or PDF:

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://stripe.com',
});
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', res);

For Playwright regression tests, keep the assertion option above: it controls animation handling in that test. ScreenshotNeo is for URL-based captures and offers controls such as full-page or element capture, viewport and device presets, custom CSS and JavaScript, waits, headers, cookies, caching, and asynchronous jobs. The plan includes 1,000 screenshots a month free with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month, with no card.

8. FAQ

Does disabling animations test accessibility?

No. Use reduced-motion emulation to test how the page responds to a user’s motion preference. The screenshot option serves stable capture.

Does the option cover Web Animations?

Yes. Playwright documents the disabled setting as covering CSS animations, CSS transitions, and Web Animations.

Will a custom CSS override stop JavaScript updates?

No universal guarantee exists. Synchronize with application-specific updates separately and inspect the resulting capture.