ContactSign inSign up
Contact

Animations

Chromatic proactively pauses CSS animations/transitions, SVG animations, and videos to prevent false positives. We do this because multiple variables outside of our control make it impossible to guarantee consistent animation painting down to the millisecond.

CSS animations

By default, CSS animations are paused at the end of their animation cycle (i.e., the last frame) when your tests run in Chromatic. This behavior is useful, specifically when working with animations that are used to “animate in” visible elements. If you want to override this behavior and pause the animation at the first frame, add the pauseAnimationAtEnd configuration option to your tests. For example:

src/components/Product.stories.ts|tsx
// Adjust this import to match your framework (e.g., nextjs, vue3-vite)
import type { Meta, StoryObj } from "@storybook/your-framework";

/*
 * Replace the @storybook/test package with the following if you are using a version of Storybook earlier than 8.0:
 * import { within } from "@storybook/testing-library";
 * import { expect } from "@storybook/jest";
*/
import { expect, within } from "@storybook/test";

import { Product } from "./Product";

const meta: Meta<typeof Product> = {
  component: Product,
  title: "Product",
  parameters: {
    // Overrides the default behavior and pauses the animation at the first frame at the component level for all stories.
    chromatic: { pauseAnimationAtEnd: false },
  },
};

export default meta;
type Story = StoryObj<typeof Product>;

export const Default: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    await expect(canvas.getByText("Product details")).toBeInTheDocument();
  },
};
ℹ️ The chromatic.pauseAnimationAtEnd parameter can be set at story, component, and project levels. This enables you to set project wide defaults and override them for specific components and/or stories. Learn more »

JavaScript animations

If you’re working with JavaScript animations libraries (e.g., framer-motion), Chromatic will not have the same level of control over the animations as CSS animations and will not disable them by default. We recommend toggling off the animation library when running in Chromatic to ensure consistent visual tests and avoid false positives.

Storybook

You can conditionally disable animations using the isChromatic() utility function. For example, to turn off animations globally in framer-motion (v10.17.0 and above), you can set the MotionGlobalConfig.skipAnimations option as follows:

.storybook/preview.js|ts
import { MotionGlobalConfig } from "framer-motion";
import isChromatic from "chromatic/isChromatic";

MotionGlobalConfig.skipAnimations = isChromatic();

ℹ️ For more information on disabling animations in other libraries, refer to the library’s documentation or community resources to learn how to achieve this.

Playwright and Cypress

When using Playwright or Cypress, you can assert that specific elements are visible in the DOM to confirm an animation has finished. Alternatively, use the wait or waitForTimeout functions to wait for the animation to complete.

Another strategy is to inject a variable into the window object to disable animations. For example, in your E2E test, set the disableAnimations property on the window object to true.

tests/Product.spec.js|ts
import { test, expect } from "@chromatic-com/playwright";

test.describe("Products Page", () => {
  test("Successfully loads the page", async ({ page }) => {
    // Set a property on the the window object to disable animations.
    await page.addInitScript(() => {
      window.disableAnimations = true
    });

    await page.goto("/products");
    await expect(page.getByText("Product details")).toBeVisible();
  });
});

Then read the value of the disableAnimations property in your application code to conditionally disable animations.

// @ts-ignore
if (window.disableAnimations) {
  MotionGlobalConfig.skipAnimations = true;
}

GIFs and Videos

Chromatic automatically pauses videos and animated GIFs at their first frame, ensuring consistent visual tests without the need for custom workarounds. If you specify a poster attribute for videos, Chromatic will use that image instead.

Animations that cannot be disabled

If you cannot turn off animations (for example, if disabling JavaScript animations is complex or your library doesn’t support it), you can use a delay to allow the animation to complete before taking the snapshot.

Alternatively, ignore an element to omit a visible area of your component when comparing snapshots.

Troubleshooting

Why are my animations working differently in Chromatic?

If you’re experiencing issues with animations not being paused as expected, it is likely due to an infrastructure update. With Capture Stack’s version 6 general availability (released in February 2024), the pauseAnimationAtEnd feature was enabled by default, leading to a change in behavior. If your tests relied on the previous behavior, you need to update your tests and configure the pauseAnimationAtEnd option to false.