ScreenshotNeo

BlogHow-to

How to Test a Mobile Website Screenshot at 320 Pixel Width

Set a true 320 CSS-pixel viewport, inspect content and scrolling, and use screenshots for repeatable visual checks—not as a conformance verdict.

By the ScreenshotNeo team4 October 20269 min read

Test the page in a browser with a viewport 320 CSS pixels wide, then inspect whether ordinary content and functionality remain available without page-level horizontal scrolling. A screenshot can document the rendering or support a repeatable visual comparison, but a screenshot diff alone cannot establish accessibility conformance.

WCAG 2.1 Success Criterion 1.4.10, Reflow, uses a width equivalent to 320 CSS pixels for vertically scrolling content. It also describes this as equivalent to viewing a 1280 CSS-pixel-wide viewport at 400% zoom. The criterion concerns preserved information and functionality without requiring scrolling in two dimensions, except for content whose use or meaning requires a two-dimensional layout. See the W3C explanation of Reflow and the WCAG 2.1 success criterion.

1. What “320 pixels wide” means

Use CSS pixels for the viewport width. A phone’s physical display width and a screenshot file’s pixel width do not necessarily equal the browser’s CSS viewport width. Browser chrome, scrollbars, zoom, device scale, and emulation settings affect the relationship.

For a direct test, set the browser viewport to 320 CSS pixels. Alternatively, test the WCAG equivalence by starting with a 1280 CSS-pixel viewport and zooming to 400%. Check the browser’s actual viewport dimensions rather than relying on a device label or the nominal size of its display. W3C notes that browser UI and scrollbars can reduce the area available to the page.

A 320 CSS-pixel viewport is a useful narrow-width check. It does not mean every physical phone must have a 320-pixel display. If your test uses a screenshot service, make sure its width option means CSS viewport pixels, and distinguish that from the output image’s pixel dimensions.

2. Inspect the page at the target width

  1. Set the viewport to 320 CSS pixels wide. Record the browser, browser version, operating system, viewport height, zoom, and device scale if the result will be compared with a baseline.
  2. Review the complete page. Scroll from top to bottom. Check navigation, headings, paragraphs, images, forms, buttons, dialogs, tables, and interactive controls.
  3. Try the important interactions. Open menus, submit forms, reach validation messages, and operate controls. Confirm that visible controls are not clipped, covered, or too difficult to reach.
  4. Check for page-level horizontal scrolling. Look for clipped content and sideways movement of the overall page. Ordinary reading and interaction should not require scrolling both horizontally and vertically.
  5. Classify any two-dimensional content carefully. A map, game, video, presentation, data table, or interface that needs a persistent toolbar while manipulating content may genuinely require two-dimensional layout. Keep necessary scrolling inside that component where practical; do not treat ordinary overflowing text or layout as an exception just because it is difficult to reflow.
  6. Capture a screenshot if it helps the review. Use it as visual evidence or a regression artifact, and pair it with a functional inspection.
  7. After a fix, repeat the inspection in the same setup. A consistent context makes it easier to distinguish a real layout change from a browser-rendering difference.

3. Reproduce the check with Playwright

Playwright can set a viewport and capture a screenshot. The following runnable example uses Node.js and Playwright Test to set a 320-by-800 CSS-pixel viewport and save a full-page screenshot. It also checks the document’s horizontal overflow as a useful diagnostic; that measurement alone is not a complete WCAG evaluation, especially when the page contains a legitimate two-dimensional component.

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

test('page at 320 CSS pixels', async ({ page }) => {
  await page.setViewportSize({ width: 320, height: 800 });
  await page.goto('https://example.com', { waitUntil: 'networkidle' });

  const dimensions = await page.evaluate(() => ({
    viewportWidth: document.documentElement.clientWidth,
    documentWidth: document.documentElement.scrollWidth,
    documentHeight: document.documentElement.scrollHeight
  }));
  console.log(dimensions);

  await page.screenshot({ path: 'mobile-320.png', fullPage: true });
  expect(dimensions.viewportWidth).toBe(320);
  // Treat overflow as a prompt for review; inspect any intentional
  // two-dimensional components before deciding whether it is a failure.
  expect(dimensions.documentWidth).toBeLessThanOrEqual(dimensions.viewportWidth);
});

Save this as a Playwright test file in a project with @playwright/test installed, then run it with npx playwright test. Replace the example URL with the page under review. The strict overflow assertion is appropriate only if the page is expected to have no page-level horizontal overflow; for a page with an intentional two-dimensional component, log and review the dimensions instead of treating this assertion as the verdict.

For a visual baseline, Playwright Test also supports screenshot assertions with toHaveScreenshot(). Keep the browser, operating system, viewport, scale, fonts, and relevant rendering settings stable: Playwright warns that screenshots can vary across environments and versions. A visual comparison identifies changes, not whether those changes violate Reflow. See the official Playwright emulation documentation and visual comparisons guide.

CSS pixels versus screenshot pixels

Playwright’s screenshot scale can be set to css or device. CSS scale produces one image pixel per CSS pixel. Device scale uses device pixels, so the image can be larger on a high-DPI context even though the CSS viewport remains 320 pixels wide. Choose a scale intentionally and use the same one for baseline and current captures. See Playwright’s screenshot assertion options.

4. Fix the layout based on what is actually failing

There is no single required CSS fix. Preserve the content, reading order, and functionality while making the layout usable at the narrower width. Depending on the page, useful approaches include:

  • Switching multi-column content to one column at a breakpoint.
  • Allowing grid or flex items to wrap or stack instead of forcing a fixed-width row.
  • Constraining ordinary images to the space available, for example with max-width: 100% and an appropriate height rule.
  • Letting form labels and controls fit or wrap without overlapping or clipping.
  • Containing necessary two-dimensional scrolling within the specific component that needs it.

These are implementation techniques, not automatic guarantees. Check that the change preserves information, functionality, and a sensible reading and interaction order. W3C documents examples using media queries and grid to reflow columns, CSS max-width and height to fit images, and CSS width, max-width, and flexbox for form labels and inputs. The techniques illustrate possible routes; none is mandatory by itself.

5. Capture a 320-pixel screenshot with ScreenshotNeo

If you need an image for review or documentation, set the capture width to 320 and use a consistent capture setup. ScreenshotNeo is a website screenshot API and MCP server from ScreenshotNeo. Its API accepts familiar screenshot parameter names, including a viewport width, and can return PNG, JPEG, or WebP. See the ScreenshotNeo API documentation for request options. A screenshot is still evidence to inspect, not a conformance verdict.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://example.com \
  -d width=320 \
  -d format=png \
  -o mobile-320.png

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={
        "access_key": "YOUR_API_KEY",
        "url": "https://example.com",
        "width": 320,
        "format": "png",
    },
    timeout=90,
)
r.raise_for_status()
with open("mobile-320.png", "wb") as image:
    image.write(r.content)

Node.js

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://example.com',
  width: '320',
  format: 'png'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) =>
  writeFile('mobile-320.png', Buffer.from(await res.arrayBuffer()))
);

Keep the API key out of public client-side code and source control. For repeat comparisons, keep the target URL, viewport height, browser settings, wait condition, and output format consistent. A full-page capture can document content below the fold, while the viewport width remains the setting relevant to this test.

Or skip the browser setup

One API request can capture the page at 320 CSS pixels. The response is an image; use a browser or accessibility review to assess behavior and content.

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

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. Sign up for free and get 1,000 screenshots a month with no card.

6. Troubleshooting

Symptom Likely cause What to check or do
The browser says the viewport is 320 wide, but the screenshot file is wider. The capture uses device-pixel scale or a high-DPI device context. Check the CSS viewport separately from output image dimensions. For Playwright comparisons, select CSS or device scale deliberately and keep it consistent.
The page still scrolls sideways. A fixed-width element, long unbroken text, oversized image, or multi-column layout may exceed the viewport. Inspect the overflowing element and its parent. Decide whether it is ordinary content that should reflow or a component that genuinely needs two-dimensional layout; fix the former and contain the latter where practical.
The automated overflow assertion fails, but the page looks usable. A legitimate component such as a table or map may widen the document, or a measurement may include browser/layout details that need review. Find the element contributing to scroll width. Do not dismiss ordinary page overflow as an exception; assess the component’s purpose and the overall access to content and controls.
The screenshot differs from the baseline with no code change. Browser or operating-system version, fonts, rendering settings, hardware, dynamic content, or capture timing changed. Stabilize the environment and page state, then recapture. Review the difference rather than assuming it is a layout regression.
A mobile emulation result does not match a real phone. Emulation represents configured parameters such as viewport, screen, user agent, and touch; it is not identical to every real device and browser. Record the emulation configuration and test on a real target device when device-specific behavior matters.
The screenshot omits content that appears later. Lazy-loaded content may not have entered the viewport or loaded before capture. Scroll through the page or use a capture workflow that loads lazy images, then verify the content in the browser. Keep capture behavior consistent for comparisons.
A screenshot API returns an error or no usable image. The request may have an invalid key or URL, the page may fail to load, or the target may present a bot check. Check the request parameters and response headers. ScreenshotNeo identifies page outcomes with X-Page-Verdict and billing with X-Billed; failed loads, bot checks, and blank pages are not billed.

7. Performance, reliability, and cost

For browser automation, reuse a stable test setup and avoid comparing captures made with different browser versions, operating systems, scale settings, or viewport sizes. Dynamic page content and capture timing can create visual noise, so compare equivalent page states. Screenshot assertions are useful for repeated checks, while manual inspection remains necessary to judge functionality and true two-dimensional exceptions.

For ScreenshotNeo, choose only the capture settings needed for the review. Its free plan includes 1,000 shots per month without a card; paid plans are Starter at $5 for 3,000, Growth at $15 for 15,000, Pro at $39 for 60,000, Scale at $99 for 250,000, and Business at $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan. Only clean shots are billed; cache hits and bot checks, blank pages, timeouts, and failed loads cost nothing. Each response reports the page verdict and billing status in headers. These billing rules help with capture cost accounting, but do not change what is required to evaluate the page.

Frequently asked questions

Does WCAG require a physical 320-pixel-wide phone?

No. The criterion refers to a CSS-pixel viewport equivalent. W3C describes 320 CSS pixels as equivalent to a 1280 CSS-pixel starting viewport at 400% zoom.

Does a screenshot prove that the page passes Reflow?

No. It can show rendering at a particular width, but you must also assess whether information and functionality remain available without two-dimensional scrolling, subject to the criterion’s exception.

Should every table scroll horizontally?

Not automatically. Judge whether the table’s two-dimensional layout is genuinely needed for its use or meaning, and ensure the rest of the page remains usable. The exception is limited to parts that require that layout.

Is Playwright required?

No. It is one documented way to set viewport parameters and capture repeatable screenshots. Manual browser inspection and other suitable test setups can also be used.