Skip to content

[ Rendering Bug ] Backdrop filter output is not clipped to the rounded border box #901

Description

@endink
Image

An element with both border-radius and backdrop-filter: blur(...) applies the blur outside its rounded border
shape when rendered with the AnyRender Skia backend. The filtered output appears in the rectangular corner areas
bounded by the element's border-box bounding rectangle.

The backdrop filter may sample pixels outside the element so that blur has enough input, but its final composited
output should remain clipped to the element's rounded border box.

Minimal reproduction

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Rounded backdrop-filter clip reproduction</title>
    <style>
        html, body { height: 100%; margin: 0; }
        body { display: grid; place-items: center; background: #111827; }
        .backdrop {
            position: relative;
            width: 360px;
            height: 220px;
            background: conic-gradient(
                #ef476f 25%, #ffd166 0 50%, #118ab2 0 75%, #06d6a0 0
            ) 0 0 / 32px 32px;
        }
        .glass {
            position: absolute;
            inset: 40px 60px;
            box-sizing: border-box;
            background: rgb(16 26 42 / 45%);
            border: 4px solid white;
            border-radius: 52px 12px;
            backdrop-filter: blur(12px);
        }
    </style>
</head>
<body>
    <div class="backdrop"><div class="glass"></div></div>
</body>
</html>

Steps to reproduce

  1. Render the HTML above with Blitz using the AnyRender Skia backend.
  2. Inspect the checkerboard immediately outside the rounded corners of the white glass panel.
  3. Compare the result with a browser rendering of the same HTML.

Actual result

The checkerboard is blurred in the rectangular corner areas outside the panel's rounded border. The visible filter
output follows the axis-aligned border-box bounds instead of the rounded border shape.

Expected result

Only pixels inside the rounded white border are composited with the blurred backdrop. Pixels outside the rounded
corners remain sharp and unchanged. No overflow: hidden should be required on the filtered element or its parent.

Possible implementation location

Based on reading the current code, the likely location of the problem appears to be
BlitzDomPainter::render_element in packages/blitz-paint/src/render.rs. That function derives the effect-layer
clip with:

let mut effect_layer_clip = cx.frame.border_box_path().bounding_box();

One possible cause is that bounding_box() may discard the rounded geometry before the clip is passed through
PaintScene::push_layer. The Skia backend appears to clip the saved layer using the shape it receives, but the shape
may already be a plain rectangle at that point.

A potential fix may belong in packages/blitz-paint/src/render.rs, specifically
BlitzDomPainter::render_element. Backdrop sampling expansion and backdrop output clipping may need to remain
separate concepts: the exact rounded border path could be retained for backdrop-filter output while the blur operation
is still allowed to read the required pixels outside that path. If regular filter and backdrop-filter are
present together, separate nested effect layers may be required.

This explanation is a hypothesis from code inspection and has not yet been confirmed by implementing and validating a
fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions