ScreenshotNeo

BlogHow-to

How to Test Responsive Web Pages with Happo Screenshots

Set up repeatable responsive screenshot checks with Happo: choose viewport and browser targets, capture key UI states, and review visual changes in CI.

By the ScreenshotNeo team4 October 20268 min read

To test responsive web pages with Happo, configure browser targets at the viewport sizes that matter to your breakpoints, capture the same important UI states at each target, and compare those screenshots with a baseline in CI. Start with a small matrix of pages, states, and browser sizes; expand it when a width or browser covers a meaningful risk. Happo’s visual comparisons can reveal spacing, wrapping, overflow, and styling changes that functional assertions alone may miss.

1. Choose the pages, states, and viewport matrix

Begin with layouts where a regression would affect a key task: navigation, checkout, dashboards, forms, and responsive components. Decide which states need coverage. A useful starting set might include the normal page, an expanded mobile menu, a validation error, and an empty or loading state. Keep state names consistent between runs so the baseline comparison is meaningful.

Choose widths based on your own CSS breakpoints, supported devices, and known failure patterns. One narrow and one desktop width can catch many changes, but include an intermediate width when it exercises a distinct layout transition. Avoid multiplying every page by every browser and width without a reason: each additional variant creates another screenshot to review and contributes to usage.

Coverage dimension Choose it based on Example
Page or component User impact and likelihood of shared layout changes Primary navigation or checkout
UI state Content or interaction that changes layout Menu expanded or form error shown
Viewport Application breakpoints and supported audience 375×812 and 1440×900
Browser target Browser engines and platforms your product supports Chrome plus iOS Safari when mobile Safari matters

2. Configure Happo browser targets

Happo looks for a happo.config file in the working directory. Targets specify a browser type and, for configurable targets, a viewport string. The following is a representative configuration using documented target syntax; select widths and browser types that fit your app. See the Happo configuration guide for the current schema and available settings.

module.exports = {
  targets: {
    chromeDesktop: {
      type: 'chrome',
      viewport: '1440x900',
    },
    chromeNarrow: {
      type: 'chrome',
      viewport: '375x812',
    },
    firefoxCompact: {
      type: 'firefox',
      viewport: '320x640',
    },
    edgeTablet: {
      type: 'edge',
      viewport: '800x600',
    },
  },
};

Documented configurable viewport bounds are 300×300 through 2000×2000 pixels. The documented target types include Firefox, Chrome, Edge, Safari, iOS Safari, iPad Safari, and accessibility. The ios-safari target uses a fixed 375×667 iPhone viewport, and ipad-safari uses a fixed 1080×810 viewport; those dimensions are not arbitrary configurable sizes. Browser-target access depends on the Happo plan, so check the current plan details before designing a required matrix.

Use the API’s width and height fields when you need to understand or construct screenshot objects directly; consult the Happo API reference for the current request and report structures.

3. Capture repeatable UI states

Prefer an integration that matches how the UI is already represented in your project. Happo documents Cypress, Playwright, and Storybook workflows. Cypress can add screenshots to existing end-to-end tests for important states; Playwright and Storybook can capture states represented by tests or stories. For pages outside those integrations, Happo’s pricing FAQ points to its generic API and integration guide.

For each capture, make the state deterministic: use stable test data, reach the same route and interaction state, and ensure the relevant content has loaded before the snapshot. Capture a named state at every target in the matrix. For example, if the mobile menu is a risk, capture it open at narrow and intermediate widths rather than only capturing the default desktop page.

Happo’s Cypress visual testing page describes adding visual snapshots to existing tests and reviewing results through CI pull-request links. It also describes side-by-side, diff-highlight, and swipe views. These comparison views help locate a change; a reviewer still decides whether the difference is expected.

4. Compare against a baseline in CI

  1. Run the same test or story and target matrix on the baseline revision.
  2. Run it again for the proposed change in CI.
  3. Open the resulting comparison for each state and target.
  4. Inspect changed regions for overflow, clipped controls, overlap, changed line wrapping, spacing shifts, and navigation changes.
  5. If a difference is intentional, review it and accept the updated baseline according to your team’s review workflow.

Do not treat a changed screenshot as automatically wrong or automatically safe. A new design can create a legitimate diff, while an accepted baseline can also encode an unnoticed regression. Record why a meaningful baseline change is expected, especially for shared components used across many pages.

5. Reduce rendering noise carefully

Happo documents animation handling, waiting for asynchronous assets and fonts, and color-delta tolerance. CSS animations are frozen on the last frame by default; the configuration guide documents freezeAnimations for first-frame behavior and animate for animated snapshots. Comparison options include compareThreshold, ignoreThreshold, ignoreWhitespace, and blur behavior. Use the exact option syntax from the current configuration guide.

Tune noise controls only after looking at the diffs. A tolerance that hides tiny antialiasing differences may also obscure a subtle border, icon, or text change. If a difference matters at one responsive width, avoid broad ignore rules that suppress it across the entire suite.

Tall pages and viewport-relative layouts

Happo documents a tall screenshot fallback for Chrome and Firefox. Pages taller than 4000 pixels may use a viewport-resizing workaround, which can affect content sized with 100vh. The setting useFullPageFallbackForTallScreenshots: false disables that workaround. If a page’s footer, sticky controls, or viewport-relative panels differ unexpectedly in a full-page capture, check this behavior and compare with a viewport-sized capture.

6. Estimate snapshot volume and cost

Happo defines a snapshot as one screenshot of a component variant in one browser. Its estimate is:

component variants × browsers × Happo runs per month

A run usually happens once per CI build, so estimate how often the relevant workflow runs each month. For example, 12 variants across 3 browsers and 40 runs would be 1,440 snapshots. This estimate is useful for planning, but check the pricing page before publishing or committing to a plan because quotas and prices can change.

As listed on Happo’s pricing page when this research was checked on 2026-10-03, Free included 5,000 snapshots per month in Chrome; Pro was listed at $749 per month for 300,000 snapshots, with $0.006 per additional snapshot; Enterprise was custom priced and listed 1M+ snapshots. The page says Free has no time limit or card requirement and that Free accounts pause at quota until an upgrade or the next cycle; paid-plan overages are charged at the stated overage rate. Verify the current Happo pricing before relying on these figures.

7. Troubleshooting responsive screenshot tests

Symptom Likely cause What to check
Target or configuration is rejected Unsupported target name, malformed viewport string, or dimensions outside documented bounds Use a documented browser type, a WIDTHxHEIGHT viewport between 300×300 and 2000×2000, and confirm your plan includes the target.
iOS Safari or iPad capture ignores the requested size Those targets use fixed documented dimensions Use the target for its fixed device viewport, or use a configurable browser target for another size.
Diff changes between identical commits Animations, asynchronous assets, fonts, or dynamic page content are not in a stable state Wait for the required content, use documented animation controls, and make test data deterministic before increasing tolerance.
Mobile layout looks clipped only in a full-page image A tall screenshot fallback can affect 100vh content Check whether the page exceeds 4000 pixels and review useFullPageFallbackForTallScreenshots; compare a viewport-sized capture.
Visual regression is missed The matrix omits the width or state where the layout changes, or comparison suppression is too broad Add a target at the meaningful breakpoint and inspect ignore, blur, and threshold settings.
CI usage grows unexpectedly Variants, browser targets, or CI runs increased Recalculate variants × browsers × runs; remove low-value combinations and verify the current plan quota.
Baseline update hides a real bug A changed image was accepted without reviewing the responsive states Review each changed target and state before accepting; verify overflow, wrapping, and controls at narrow widths.

8. Practical reliability and performance notes

  • Keep the matrix reviewable. Add coverage where it tests a distinct breakpoint, browser engine, or important state. A very large matrix increases snapshot volume and review work.
  • Stabilize before loosening comparison. Wait for fonts and relevant assets and control animations. Broad thresholds can conceal the exact small layout changes responsive testing is meant to catch.
  • Use the same capture recipe. Consistent routes, state setup, viewport targets, and test data make baseline diffs easier to interpret.
  • Review CI diffs as part of the change. A screenshot tool reports visual differences; the team must decide whether each difference is intended.
  • Budget from actual CI frequency. Estimate monthly snapshots using the number of variants, browsers, and runs, then compare with the current plan terms.

Or skip the browser setup

If you need a screenshot endpoint for a page or a separate capture workflow, ScreenshotNeo is a website screenshot API and MCP server. A single request can return an image or PDF; this example saves the response body as a WebP file. See the ScreenshotNeo API documentation for request options.

cURL

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

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

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}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));

ScreenshotNeo removes known cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account to get started.

FAQ

Does a screenshot test replace responsive functional tests?

No. Visual comparisons reveal appearance changes, while functional tests check behavior. Use both for important interactions and layouts.

Should every breakpoint be a Happo target?

Cover widths that represent meaningful layout changes or known risks. Add more where a distinct breakpoint or browser-specific issue justifies the extra snapshots.

Can I use Happo for component-level checks?

Yes. Happo documents Storybook and other integrations for capturing component states, alongside end-to-end workflows for page states.

What should I do when a visual difference is intentional?

Review the affected state and viewport, confirm the change is expected, then update the baseline through your team’s review process.