Summary
In Firefox with the WebRender layer compositor (hardware overlay promotion), an animated WebGL canvas escapes border-radius, overflow: hidden, and clip-path — including its own border-radius — after its fade-in completes. The corners of the container are painted over with a square canvas.
Frozen canvases (one frame) are unaffected. The bug is not in this library, but this library is an easy way to hit it: any animated shader inside a rounded container.
Environment
- Firefox (macOS, GPU compositing active — WebRender layer compositor / native surfaces)
@paper-design/shaders-react 0.0.80
Steps to reproduce
- Open Firefox on macOS with hardware acceleration enabled (layer compositor active).
- Render an animated shader (
speed > 0) inside a container with border-radius and overflow: hidden, with a fade-in (opacity transition) on a wrapper.
- Wait for the fade-in to complete.
Minimal repro without this library (same mechanism):
<!doctype html>
<style>
body { background: #faf8f1; }
.shell { width: 600px; height: 400px; border-radius: 40px; overflow: hidden; background: #111; }
.wrap { height: 100%; opacity: 1; transition: opacity 800ms; }
canvas { width: 100%; height: 100%; display: block; border-radius: inherit; }
</style>
<div class="shell"><div class="wrap"><canvas id="c"></canvas></div></div>
<script>
const gl = document.getElementById("c").getContext("webgl2");
requestAnimationFrame(function frame(t) {
const s = 0.5 + 0.5 * Math.sin(t / 1000);
gl.clearColor(0.2 * s, 0.15 * s, 0.5 * s, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
requestAnimationFrame(frame);
});
</script>
Expected
Corners stay rounded.
Actual
Once the fade-in finishes, the canvas paints as a square over the corner (verified by pixel measurement: canvas-colored pixels 3px from the corner vertex, shader pattern visible inside the cut region).
Why only the animated shader
- The only canvas that breaks on our page is the animated one (
speed: 0.35). Frozen shaders (speed: 0 + fixed frame, e.g. the footer blend layers) are rasterized once and composited as normal images, so ancestor clips always apply.
- While the fade-in runs (
opacity < 1), the subtree renders into an intermediate surface and clips apply. When opacity reaches 1, Firefox promotes the continuously-presenting canvas to a hardware overlay, which ignores rounded clips.
Root cause (Firefox)
- Bug 2002563 — "Video content inside position:fixed container ignores border-radius when using new layer compositor" (VERIFIED FIXED, Firefox 148, Dec 2025). Same mechanism for video overlays; the fix was "Add overlay's rounded clip rects handling to WebRender layer compositor".
- Bug 2005103 — follow-up: "Use overlay with video rendering with rounded rects if possible".
- Bug 1958603 — WebGL/WebGPU overlay support (IDCompositionTexture) landed Jan 2026, after the video rounded-clip fix.
- Bug 2038378 — "Re-enable WebGL/WebGPU overlay on Windows" (open): WebGL overlay was disabled again on Windows.
So the WebGL overlay path appears to lack the rounded-clip handling that video overlays got in Firefox 148.
Workaround
Keep the shader wrapper's opacity slightly below 1 (e.g. 0.9999) so the subtree always composites through an intermediate surface and never gets promoted to an overlay. Visually indistinguishable; confirmed working.
Summary
In Firefox with the WebRender layer compositor (hardware overlay promotion), an animated WebGL canvas escapes
border-radius,overflow: hidden, andclip-path— including its ownborder-radius— after its fade-in completes. The corners of the container are painted over with a square canvas.Frozen canvases (one frame) are unaffected. The bug is not in this library, but this library is an easy way to hit it: any animated shader inside a rounded container.
Environment
@paper-design/shaders-react0.0.80Steps to reproduce
speed > 0) inside a container withborder-radiusandoverflow: hidden, with a fade-in (opacity transition) on a wrapper.Minimal repro without this library (same mechanism):
Expected
Corners stay rounded.
Actual
Once the fade-in finishes, the canvas paints as a square over the corner (verified by pixel measurement: canvas-colored pixels 3px from the corner vertex, shader pattern visible inside the cut region).
Why only the animated shader
speed: 0.35). Frozen shaders (speed: 0+ fixed frame, e.g. the footer blend layers) are rasterized once and composited as normal images, so ancestor clips always apply.opacity < 1), the subtree renders into an intermediate surface and clips apply. When opacity reaches 1, Firefox promotes the continuously-presenting canvas to a hardware overlay, which ignores rounded clips.Root cause (Firefox)
So the WebGL overlay path appears to lack the rounded-clip handling that video overlays got in Firefox 148.
Workaround
Keep the shader wrapper's opacity slightly below 1 (e.g.
0.9999) so the subtree always composites through an intermediate surface and never gets promoted to an overlay. Visually indistinguishable; confirmed working.