Which browser is the wrong cross-browser question

Most cross-browser issues are settled by the viewport, the pixel ratio, the console error and the failed request before the browser name. Capture in that order.

Four clear glass lenses surround an orange viewport frame on a black stage

A report that says it is broken on my browser gets one reply: which browser? That is the wrong first question. The browser name settles fewer cross-browser issues than the viewport, the pixel ratio of the screen, the error that fired in the console and the request that failed. Capture those first, and ask about the browser last.

The browser name settles fewer reports than it starts

Ask which browser and the answer is a name that moves the investigation nowhere. The developer opens that browser, loads the page, and it works. The report is now “works for me on Chrome”, which is where it started, with one round trip spent.

The reason is that the label “cross-browser issue” covers several different failures, and most of them are not about the rendering engine. A layout that collapses at one width is a viewport issue that happens to show on the reporter’s laptop. A blurry icon or a hairline border that vanishes is a pixel-ratio issue that happens to show on the reporter’s display. A button that does nothing is a script error, and the console names it in one line whether the cause is an API missing from one engine or a bug that fires in all of them. An engine-specific difference, a CSS property one engine implements and another does not, or a JavaScript API missing in one, is real, and it is one bin among several. The label puts every report into that one bin.

So the first question sorts the reports wrongly. Asking which browser treats every report as an engine report, and most of them belong somewhere else.

What the reporter says, and what decides it

What the reporter saysWhat usually decides itWhere the deciding fact is
“The layout is broken on my browser”The viewport width, and the breakpoint it fell onThe window size at the moment of the report
“The icons are blurry” or “the line is missing”The device pixel ratio, and an asset or border sized for one ratioThe screen, not the browser
“The button does nothing”An uncaught exception in a handler, thrown before the click reached the code that would actThe console, in the seconds before the report
“It never loads”A request that failed, was blocked, or timed outThe network log, with the status
“It works on my laptop but not my phone”Touch versus pointer, or a hover state with no touch equivalentThe device class and the input type
“It looks different in Safari”An engine difference, the one case the browser name settlesThe browser and version, plus the property in question

Only the last row is decided by the browser name, and even there the name is not enough. The version matters, and on iOS a browser called Chrome or Firefox renders with the same WebKit engine as Safari under Apple’s App Store guideline 2.5.6, except where Apple grants an entitlement for another engine, which it does in some jurisdictions, so “Chrome on iPhone” is a Safari engine report wearing a different toolbar.

Every other row is decided by something the reporter cannot see and would not think to mention. The viewport is a number nobody knows about their own window. The device pixel ratio is a property of the display that most people have never heard of. The console is a panel most reporters have never opened. Asking for any of these gets the same result as asking for the browser: a guess, or a shrug.

Order the capture by what settles a report

The list of what to capture follows from the table, and the order matters because a capture list gets trimmed under pressure and whatever sits at the bottom goes first.

First the viewport, at the moment of the report, because a layout complaint is a breakpoint question before it is a browser question. Second the device pixel ratio alongside the screen dimensions, because it separates “the asset is wrong” from “the asset is wrong on this display”. Third the console, meaning every uncaught exception and logged error from the seconds before the report, because a script error explains a dead button in one line and no amount of matrix testing finds it faster. Fourth the network log with statuses and timings, because “it never loads” is a failed request, and the request names itself. Then the browser, its version, the operating system and the device class, which together settle the last row and give the engine bin its one real input.

None of that can be asked for; it has to be taken from the page at the moment the reporter files. With evidence capture on the page, every item on that list is on the report when it lands: the viewport and the screen, the console lines from the session, the network activity with its statuses, and the browser, operating system and device the reporter would otherwise have guessed at. The developer reads which row of the table the report sits in before writing a reply.

The capture stops at the bodies: it does not record what a request or response contained, so a request that failed because of what was in it still needs the reporter’s input to reproduce. It also records only what the page could see, so a browser extension that rewrote the DOM, or an enterprise policy that blocked a script, shows up as its effect and not as its cause.

The matrix decides what to reproduce by hand

Capture tells you which bin a report is in. It does not tell you which browsers to test before the report arrives, and it does not replace that test. A test matrix does that job, and the table above changes what goes in it.

Rows for viewports and pixel ratios belong in the matrix ahead of rows for browser versions, because they decide more reports. A headless browser in the pipeline covers the width rows cheaply: render the page at each breakpoint, compare, and the layout bin empties before release. It covers pixel ratios by emulation, which picks the assets and rounds the borders the way a display at that ratio would, and it does not cover touch at all, nor does a headless build of an engine stand in for the browser that ships it. Those rows are reproduced on hardware, and the matrix says which hardware, so that the reporter’s “my phone” has a row it can be checked against.

The engine rows stay, and they shrink. Two or three engines at the versions the captured reports show is a matrix somebody will run. A grid of every browser at every version is a matrix nobody runs, and a matrix nobody runs protects nothing.

An emailed report arrives with nothing attached

The limit is the reporter you have no tag in front of. A customer who emails support instead of filing from the page, one whose machine blocks the widget script by policy or by an ad blocker, or one reporting a page you do not host, such as a checkout on a payment provider’s domain, files the same report as everybody else, and it arrives with nothing attached. For that reporter the capture list becomes a question list again, and the questions have to be the ones from the table: how wide is the window, does the page look sharp, did anything appear in red for anyone who knows where to look, does it load at all.

There is a second limit in the browser name itself, and it is getting tighter. Chrome has reduced what its user-agent string reveals: the minor version, the operating system version and the device model are frozen or generic, so a string that used to identify a device now identifies a family. The detail moved to Client Hints, which a page has to ask for and a browser can decline to give. The browser field on a report is a coarser fact than it was, which is one more reason to put it at the end of the list rather than the start. What the reporter’s window was doing, what the console said and what the network returned did not get coarser, and they are what settle the report.

Common questions

What causes most cross-browser issues?

Most reports filed as cross-browser issues are decided by something other than the rendering engine: a layout that collapses at one viewport width, an asset or border sized for one device pixel ratio, an uncaught exception that killed a click handler, or a request that failed. Genuine engine differences exist and are the smaller bin, so sort the report before opening a second browser.

What information should a cross-browser bug report include?

In order of what settles a report: the viewport at the moment of filing, the device pixel ratio and screen size, the console errors from the seconds before, the network requests with their statuses, and only then the browser, its version, the operating system and the device class. None of that can be asked of a reporter, so the page has to attach it.

Why does a bug reproduce in Safari on iPhone but not in Chrome on iPhone?

Usually the two reports differ in something other than the engine, because every browser on iOS renders with WebKit under Apple's App Store rules, except where Apple grants an entitlement for another engine, which it does in some jurisdictions, so a browser named Chrome on an iPhone is a Safari engine with a different toolbar. Check the viewport, the pixel ratio and the console before treating it as an engine difference.

Can a headless browser find cross-browser issues?

A headless browser covers the viewport rows of a test matrix cheaply: render each breakpoint, compare, and the layout bin empties before release. It covers pixel ratios by emulation, which is good enough for asset selection and rounding, and it does not cover touch or stand in for the shipped browser. Those rows are reproduced on hardware the matrix names.

How do you reproduce a cross-browser issue from a user's report?

Read which row of the sorting table the report lands in before opening any browser. A viewport, a pixel ratio, a console error or a failed request each name a reproduction on its own. Only a report that survives all four as an engine difference needs the browser and version, and that is where the matrix says which hardware to reach for.

Does the browser version still matter for a cross-browser bug report?

The version matters for the genuine engine differences, and it is a coarser fact than it was: Chrome's user-agent reduction froze the minor version, the operating system version and the device model, so the string identifies a family rather than a device. The viewport, the console and the network log did not get coarser, which is why they lead the capture list.

The Notarus team

The people who build Notarus. We write up the decisions behind the product when the reasoning is worth more than the changelog line.

Keep reading

Reports with the evidence attached.

Start free, one script tag.

<script src="…/widget.js" data-key="pb_pub_…">