Experimental paint-only CSS corner-shape fallback using WebKit and Gecko live-image backends. Import Cornerfill once, write normal CSS, and leave the qualified Chrome path native.
| Chrome (native) | WebKit (Cornerfill) | Firefox (Cornerfill) |
|---|---|---|
![]() |
![]() |
![]() |
These are real Playwright engine captures of the same matrix3d() animation. WebKit and Firefox stayed at one Cornerfill paint across all 24 frames. They demonstrate the three rendering paths, not certified pixel parity or direct Safari Stable/Firefox Stable qualification.
npm install cornerfillImport Cornerfill once at your application entry:
import "cornerfill";Apps that need to gate initial paint, inspect the selected path, or tear down an app shell can retain the controller:
import cornerfill from "cornerfill";
if (cornerfill) {
await cornerfill.ready;
console.log(cornerfill.explain());
// cornerfill.destroy(); when the app shell is removed
}Then write ordinary CSS:
.triangle {
width: 120px;
height: 100px;
border-radius: 50% 50% 0 0 / 100% 100% 0 0;
corner-shape: bevel bevel round round;
background: #f05a47;
}That's it. Cornerfill discovers the CSS automatically; no build transform or custom carrier declarations are required. Chrome stays native when it passes Cornerfill's syntax, computed-value, and shaped-hit-test proxy. In WebKit and Gecko, an available live-image fallback remains preferred until the engine also qualifies for the native paint semantics that proxy does not certify.
Fallback browsers can discard unsupported corner-shape declarations before computed style exposes them. Cornerfill recovers accessible authored CSS, lets the browser resolve its cascade, and paints the resulting host background and supported border into a transparent Canvas surface.
WebKit displays that surface with -webkit-canvas(). Firefox registers it with mozSetImageElement() and displays it with -moz-element(). The image stays on the original element, so layout, opacity, stacking, and transforms such as matrix3d(...) remain browser-owned. Transform-only animation does not repaint the surface.
Cornerfill does not use clip-path, CSS masks, SVG or font stencils, or baked-alpha assets.
Every fallback paint path below is experimental. Native-versus-candidate pixel parity remains UNQUALIFIED.
round,squircle,square,bevel,scoop,notch, finitesuperellipse()corners, physical and logical properties, and browser-computedborder-radiusvalues.- Solid colors and static same-origin or CORS-enabled raster backgrounds with supported sizing, positioning, repetition, origin, and clip. Native CSS image sampling and Canvas
drawImage()can drift at raster edges, so raster pixel parity is explicitly unqualified. - Non-repeating gradients with supported geometry. Canvas does not reproduce default CSS gradient color interpolation, so gradient color parity is explicitly unqualified.
- One-color solid borders with unequal widths, one inset shadow, and one contained solid outline.
- Inline, embedded, and readable linked CSS, including imports, variables, media queries, layers, observable focus/hover/open/fullscreen selectors, and registered open shadow roots.
- Resize plus discovered source, class, attribute, inline-style, and observable selector-state changes update automatically.
Unsupported syntax is reported or left native rather than approximated.
- Cornerfill shapes host paint. It does not provide descendant overflow clipping, shaped hit testing, replaced-content clipping, multi-fragment boxes,
backdrop-filterclipping, or automatic pseudo-element targets. A fallback host whose computed overflow is notvisibleis refused even while empty. - Outer shadows and outlines,
border-image, per-side border colors, non-solid borders, animated CSS images, repeating gradients, and general background blending are not implemented. Conflicting!importantpaint declarations are rejected. - A contained painted outline requires an empty, paint-owned host. Any open shadow root counts as foreground content because later shadow-tree mutations cannot safely preserve that contract.
- Cross-origin raster images without CORS are unsupported even when native CSS could display them.
- Linked and imported CSS source is recovered through a separate
fetch(), so CSP must permit it throughconnect-src. A blocked or unreadable source fails automatic ownership closed for its root; dynamically varying responses require exact source handoff. - CSS animations and transitions of shape or paint inputs do not reproduce native timing.
- Direct
dirchanges are observed. Content-driven direction changes underdir=autoare not tracked across arbitrary descendant text and require an explicit refresh. - Closed shadow roots, unreadable cross-origin CSS, and linked/imported CSS that is not UTF-8 fail automatic ownership closed by default. Unobservable selector states such as programmatic
:checked,:target, and:visitedare refused instead of becoming stale. insertRule()anddeleteRule()are observed only on the top-levelCSSStyleSheetowned by a readable<style>or<link>element. Imported child sheets and adopted stylesheets still require their documented explicit source handoff.- Direct mutation of existing CSSOM declarations, selectors, grouping rules, or media lists requires exact authored source through
replaceStylesheetSource(); genericrefresh()cannot reconstruct source the browser no longer exposes. - The explicit
cornerfill/runtimeobserver covers host class, inline style, content, and size. Callhandle.refresh()orcontroller.refresh()after other cascade inputs change.
npm test
npm run test:package
npm run test:browser:runtime
npm run oracle:cross # all 17 portable cases, serially in three enginesBrowser tests run Chrome, WebKit, and Firefox one at a time. TypeScript .mts files are the source of truth. See the implementation contract and oracle contract for details.
Cornerfill is MIT licensed.


