How to Test Responsive Layouts with Argos CI Screenshots
Build stable responsive screenshot checks with Playwright and Argos CI. Choose meaningful viewports, establish a baseline, and review diffs with the right context.
To test responsive layouts with Argos CI, run the same page state in Playwright at explicitly chosen viewport sizes, capture each state with Argos’s Playwright helper, and upload the captures through the Argos reporter in CI. Keep viewport and browser conditions consistent, stabilize fonts, images, and asynchronous content, and run the default branch first to create the baseline used for pull request comparisons. Argos records viewport context so reviewers can tell which responsive state they are inspecting.
1. Choose viewport cases from your interface
There is no universal viewport matrix that fits every product. Start with the layout transitions your CSS and interface actually have, then choose a stable width on either side of each important transition. Include special states that carry layout risk, such as a collapsed navigation, a multi-column region becoming a single column, or a content panel becoming scrollable.
Keep the matrix small enough to review, but broad enough to cover important user-facing changes. Name cases by their purpose and dimensions rather than relying on ambiguous labels such as “mobile.” For example, nav-collapsed-390x844 communicates more than mobile. The sizes below are examples only; choose values based on your app’s breakpoints and supported layouts.
| Case | Example dimensions | What to inspect |
|---|---|---|
| Narrow layout | 390 × 844 | Navigation collapse, readable content width, horizontal overflow |
| Transition edge | 768 × 1024 | Wrapping, gaps, and column changes near a product breakpoint |
| Wide layout | 1440 × 900 | Maximum content width, alignment, and multi-column layout |
Viewport width and height are both part of the capture condition. A fixed width with a changing height can alter which content is visible in a viewport-sized screenshot, while page layout and sticky elements may also depend on available height. Argos screenshot metadata supports recording both values. See the Argos screenshot metadata reference.
2. Add Argos to Playwright
Follow the current Argos Playwright Quickstart for the current package installation and reporter configuration. The integration’s core capture call is argosScreenshot(page, "homepage"). The example below extends that capture pattern to run named cases at explicit viewport dimensions.
import { test } from "@playwright/test";
import { argosScreenshot } from "@argos-ci/playwright";
const responsiveCases = [
{ name: "nav-collapsed-390x844", width: 390, height: 844 },
{ name: "transition-768x1024", width: 768, height: 1024 },
{ name: "wide-1440x900", width: 1440, height: 900 },
];
test.describe("homepage responsive layouts", () => {
for (const viewport of responsiveCases) {
test(viewport.name, async ({ page }) => {
await page.setViewportSize({ width: viewport.width, height: viewport.height });
await page.goto("http://localhost:3000", { waitUntil: "networkidle" });
await page.evaluate(() => document.fonts.ready);
await page.locator("main").waitFor({ state: "visible" });
await argosScreenshot(page, `homepage-${viewport.name}`);
});
}
});
This is a Playwright test file; the local server at http://localhost:3000 must be running before the tests execute. Replace the URL and readiness condition with your app’s route and a reliable signal that the particular page state is ready. If your suite uses Playwright projects to define browser or viewport configuration, you can use those instead; what matters is that every named capture gets repeatable dimensions and conditions.
networkidle can be useful for pages that settle after requests finish, but it is not a universal readiness signal. Applications with polling, long-lived connections, or delayed client rendering should wait for a specific element or application state rather than assuming network quiet means the visible content is final. See Argos’s guidance on flaky visual tests.
3. Stabilize the capture state
A responsive screenshot comparison is only meaningful when the baseline and new capture represent the same page state. Before capture:
- Navigate at the target viewport where practical. Responsive images can select different
srcsetresources at different widths. - Wait for the important content, fonts, and images to be ready. Use an app-specific ready marker when asynchronous data affects the layout.
- Disable or finish animations and transitions that make pixels vary between runs. Avoid capturing a blinking caret or transient loading indicator.
- Keep browser, viewport, route, user state, content fixtures, and relevant environment settings consistent.
- Check scrollbars and page height when they affect layout or screenshot dimensions.
Playwright can wait for image elements to finish loading and decoding. Adapt the condition if your page intentionally has images that load lazily below the fold:
await page.evaluate(async () => {
await document.fonts.ready;
const images = Array.from(document.images);
await Promise.all(images.map(async (image) => {
if (!image.complete) {
await new Promise((resolve) => {
image.addEventListener("load", resolve, { once: true });
image.addEventListener("error", resolve, { once: true });
});
}
if (image.decode) {
try { await image.decode(); } catch { /* A failed image should be diagnosed separately. */ }
}
}));
});
Do not treat the snippet as proof that all page assets are correct: a failed image also completes, so inspect expected assets or wait for an application-level success condition if missing images would make the capture invalid. Argos discusses image stabilization and responsive image behavior in A journey to image stabilization.
4. Configure the reporter and run in CI
Add the Argos reporter using the configuration shown in the current official quickstart. The package setup and authentication instructions may change, so use that source rather than an old copied configuration. The quickstart demonstrates GitHub Actions with ARGOS_TOKEN and notes that GitHub Actions can use OIDC or tokenless authentication.
Run the same Playwright command locally and in CI, with the same app build, browser setup, test data, and responsive cases. Keep secrets in the CI secret mechanism if using a token. A basic sequence is:
- Install the project dependencies and the Argos Playwright integration according to the quickstart.
- Start the application or preview server in the CI job.
- Run Playwright with the Argos reporter enabled.
- Provide the supported Argos authentication for your CI provider.
- Wait for the upload to complete and inspect the resulting build.
Use the precise reporter block and workflow syntax from the official quickstart, since those details are version- and provider-sensitive.
5. Establish a baseline, then review changes
Run the workflow on the default branch first. Argos’s quickstart says pull request builds are marked orphan until a default-branch build exists. Once that baseline is available, pull request captures can be compared against it. Keep capture names stable across runs; a changed name can prevent the comparison from matching the intended screenshot.
For each reported difference, inspect the screenshot and its context rather than treating a pixel diff as an automatic diagnosis. Argos’s diff view provides context such as URL, viewport, color mode, browser, test title, and location, and supports switching among viewport or browser variants. See Argos Diff and the variant selector description.
| Review axis | Questions to ask |
|---|---|
| Viewport | Did the layout wrap, collapse, overflow, or leave a gap at this width? |
| Browser | Does the change appear across captured browsers, or only one? |
| Page state | Is this the intended route, content, and interaction state? |
| Stability | Does the difference reproduce, or do fonts, images, animation, or async data vary? |
| Intent | Is this an approved design change or a regression to fix? |
Approve intended design changes through your team’s normal review process. Fix unintended layout changes before merging. If a difference varies between identical runs, first remove the source of nondeterminism. A broader sensitivity setting may hide a real responsive defect and should be used only for a region that legitimately varies.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF capture; its documentation covers the API options. For visual regression suites, it can supply captures, while your tests and comparison workflow still determine which page states to check.
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}`);
Replace the target URL and keep the same viewport and page state between captures when using screenshots for comparisons. Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month, with no card.
Performance, reliability, and cost
Visual checks add browser navigation, page stabilization, capture, upload, and review work to a CI run. Keep the viewport matrix focused on meaningful layout states, and avoid duplicating identical states across tests unless the browser or route changes behavior. Stable readiness checks reduce reruns and wasted review time. The dossier does not provide Argos pricing or performance benchmarks, so check the service’s current plan details separately when estimating CI cost.
For reliable results, treat the viewport matrix, browser versions, fixtures, and page readiness signals as test inputs that should be reviewed alongside code. If responsive image selection or delayed content is important, capture at each target size from navigation onward and verify the intended content is present. Argos upload success alone does not prove the screenshot represents the intended state.
Troubleshooting
The screenshot changes dimensions or layout between runs
Check that width and height are explicitly set and that the browser and CI environment are consistent. Viewport variation causes reflow, which can create broad diffs. Also inspect scrollbars, page content, and whether tests resize after navigation.
Text, images, or loaders appear inconsistently
Wait for the relevant content and assets to settle. Ensure fonts are ready, image loads have completed, and the app has reached an expected state. Disable or finish animation and avoid using network idle as the only signal when the page keeps making requests.
Responsive images look wrong after resizing
The browser may have selected a different srcset resource for the new width. Prefer starting a separate test at the target viewport, then verify image readiness after navigation.
Every pull request screenshot appears new
Confirm a build ran on the default branch to establish a baseline. Then check that screenshot names, route, viewport, and browser context are stable between the baseline and pull request.
A tolerance hides changes you care about
Find and remove the source of variation first. Use per-screenshot sensitivity settings sparingly, only for a region with legitimate variability; do not use tolerance to compensate for unstable viewport or content setup.
The capture is blank or shows the wrong state
Check the navigation URL, local server readiness, route authentication, and app-specific content marker. A successful navigation can occur before client-side rendering has finished, so wait for the element that proves the intended state is visible.
The Argos upload is orphaned or cannot be compared
Run the workflow on the default branch to create the baseline, following the quickstart. Also verify the configured reporter and authentication method against the current Argos CI instructions.
FAQ
Does Argos choose responsive breakpoints for my app?
No universal breakpoint list is prescribed in the reviewed sources. Select widths from your own CSS and user-critical layout transitions.
Should I resize one page or navigate once per viewport?
Separate test cases that start at their target viewport are generally easier to reason about, especially when responsive images use srcset. If you resize, explicitly verify layout and asset readiness afterward.
Does a screenshot diff tell me whether a change is a bug?
No. It identifies visual change; a reviewer must decide whether the change is intended and whether the affected responsive state remains correct.
Can I use one screenshot name for every viewport?
Give each responsive capture a distinct stable name that identifies its route and viewport case, so review context is clear and comparisons remain unambiguous.


