Catalog / Technique
Compatibility
Use before any recipe is written, and before one is marked passed: what every recipe owes every browser. Covers the three engines (Chrome and Edge, Safari, Firefox) and what each lacks today, the rest state, the second engine a recipe carries where one exists, feature tests in script, the needs readout, and what is run by hand before a recipe is passed.
- Loads as
technique-compatibility- Written for
- An agent, to follow
Compatibility
One sentence: a recipe is judged in the browser the reader has, not the one it was built in. Every recipe rests at the page as laid out, carries a second engine where the platform has one, says what it could not do, and is run by hand in the three engines before it is passed.
When to use
- Before a recipe is written: which features it rests on, in which engine each is missing, and what the recipe does there.
- Before a recipe is marked
passed: it was looked at in Chrome, in Firefox and in Safari, and did the right thing in each. - When the owner reports “it does not work”: the first question is which browser, and the bench’s readout under the stage answers it.
Do not use it to argue a feature out of the lab. A feature one engine lacks is used, with a fallback; what is refused is a recipe that works in one engine and breaks the page in another.
Rules
- Feature-test in script, at mount, once per recipe.
typeof,'x' in,CSS.supports. Never a user-agent string. The stage overridesmatchMediato preview reduced motion, and a decision made in CSS cannot see that, so motion is decided in script too. - The rest state is the page as laid out. Nothing a recipe adds is needed for the page to be read, and nothing it hides stays hidden when it cannot run. The failure path is the rest state, in every engine.
- Carry a second engine where the platform has one. The same
effect done another way, chosen by the feature test, in the same
file. Today’s pairs: cross-document view transitions, or a fetched
page swapped in under a same-document one (
page-morph); view timelines, or the same keyframes scrubbed by script on scroll (mask-settle); a shader lid, or a CSS treatment (shader-liftanddither-lift, two recipes for one idea). A second engine is the effect, not an apology for it. - The second engine is honest about its cost. A swap is a small router and runs the new body’s inline scripts only; a scrub by script is on the main thread. The doc says so.
- The bench says what the browser lacks.
demo.tslistsneeds, the stage reports what it has, and the readout under the stage says in one line why a recipe is quiet. A recipe with a second engine lists the floor it rests on, not the feature it prefers. - Never add
crossorigin, never depend on an API newer than the feature it serves.navigation.activationarrived in Safari after cross-document transitions did;PageSwapEvent.activationand the clicked link serve instead. - A Chromium-only feature is an enhancement by feature test, never a foundation: scroll-triggered animations, nested transition groups, element-scoped transitions, generated carousel controls, WebGPU.
- Firefox and Safari are run by hand. Headless Chrome drives every
check; the other two engines are not on the check’s machine. Nothing
is marked
passeduntil both have been looked at once, and the recipe’s doc records what was seen. - Write down the day. Support changes month to month (Firefox shipped scroll-driven animations in 159 three weeks after the research said it had not). Every claim here carries its date.
Decisions
| Question | Choose | Because |
|---|---|---|
| Firefox has no cross-document transitions: wait, or swap? | Swap, inside the recipe | The owner asked for every recipe to work in Firefox; the swap is the same effect by the engine Firefox has, bounded to inline scripts |
| Firefox has no view timelines before 159: wait, or scrub by script? | Scrub by script | The same move, on the main thread, until 159 lands; the feature test picks the timeline where it exists |
| No WebGL2: a CSS engine, or nothing? | A CSS recipe beside the shader one where the idea allows it | dither-lift beside shader-lift; a contour field has no CSS twin and rests at the page |
| Detect by user agent? | Never | A feature test is true the day the feature ships |
| How is a missing feature reported? | The bench’s readout, in words | Said quietly it was read past, and a recipe that could not run was taken for one that was broken |
Tuning
| Dial | Start | Range | One end | The other |
|---|---|---|---|---|
| Where the feature test runs | At mount | Mount, or at each use | A decision made once | A feature that arrives later is noticed |
| What the swap runs of a new body | Inline classic scripts | None, to everything | Stale page state | A router |
Rest state
The page as laid out. The same in every engine, under reduced motion, without script, and when a feature test fails.
Cost
- To build: a second engine is most of a recipe’s size where it
exists (
page-morphcarries about a kilobyte for the swap). - To run: a fallback engine is usually the costlier one, on the main thread or over the network; the preferred engine is chosen wherever it exists.
- To the reader: nothing, which is the point.
Checklist
- Every feature the recipe rests on has a test in script, and the recipe’s doc says what happens without it.
-
demo.tslistsneedsas the floor the recipe rests on. -
npm run check:browserexercises the second engine where one exists, by taking the preferred feature away in Chrome. - Looked at in Firefox and in Safari by hand, and what was seen is in the doc, before
passed. - Support claims carry their date.
Recipes
page-morph: cross-document transitions, or a fetched page swapped in under a same-document one.mask-settle: a view timeline, or the same keyframes scrubbed by script.shader-lift: the shader engine of an idea whose CSS engine isdither-lift.dither-lift: the CSS engine, which needs no WebGL.
Sources
bcd-view-transition-at-rule: cross-document view transitions in Chrome 126 and Safari 18.2, not in Firefoxwebdev-vt-baseline: same-document view transitions in every enginebugzilla-2020327: Firefox parses the at-rule and does not run the transition, as of May 2026bugzilla-1324602: Firefox ships scroll-driven animations in 159, due 2026-10-27bcd-animation-timeline: support for scroll-driven animationsbcd-files-2026-10-06: the engine versions behind every claim here, read on that daywebdev-interop-2026: what the engines have agreed to converge on this yearmdn-firefox-experimental: what Firefox keeps behind a preferencewcag-animation-from-interactions: motion from interaction must be possible to switch off, in every engine