Bug 246106 - [Filters] CSS filters are not applied to SVG elements
Summary: [Filters] CSS filters are not applied to SVG elements
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: SVG (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: BrowserCompat, InRadar
Depends on:
Blocks:
 
Reported: 2022-10-05 14:21 PDT by Said Abou-Hallawa
Modified: 2024-08-25 00:43 PDT (History)
10 users (show)

See Also:


Attachments
test case (an SVG <rect> with style `filter: drop-shadow(...)`) (194 bytes, text/html)
2022-10-05 14:21 PDT, Said Abou-Hallawa
no flags Details
Test case (an HTML and an SVG file) covering root SVG and inline/external symbols (1.60 KB, application/zip)
2024-06-11 21:26 PDT, azin+webkit
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Said Abou-Hallawa 2022-10-05 14:21:14 PDT
Created attachment 462818 [details]
test case (an SVG <rect> with style `filter: drop-shadow(...)`)

Open the attached test case.

Result: Only a 100x100 green rectangle is drawn
Expected: A 100x100 green rectangle with black drop shadow is drawn.
Comment 1 Said Abou-Hallawa 2022-10-05 14:21:43 PDT
rdar://95175811
Comment 2 Felix Olszewski 2024-06-03 06:54:50 PDT
Use this workaround that I discovered whilst chatting with GPT4:

"it was a webkit bug. I found it. Can you give me even more workarounds, maybe similar properties or so?"

->

Instead of relying on CSS to apply the filter, you can define an SVG filter within your SVG and apply it to the image element. SVG filters are more universally supported in terms of functionality across different browsers, including Safari.

Here's an example of how you can apply a grayscale effect using an SVG filter:

xml
Copy code
<svg width="200" height="200">
  <defs>
    <filter id="grayscale-filter">
      <feColorMatrix type="matrix" values="0.33 0.33 0.33 0 0
                                           0.33 0.33 0.33 0 0
                                           0.33 0.33 0.33 0 0
                                           0 0 0 1 0"/>
    </filter>
  </defs>
  <image filter="url(#grayscale-filter)" href="your-image-url.jpg" x="0" y="0" height="200px" width="200px"/>
</svg>
Comment 3 azin+webkit 2024-06-11 21:26:35 PDT
Created attachment 471657 [details]
Test case (an HTML and an SVG file) covering root SVG and inline/external symbols
Comment 4 azin+webkit 2024-06-11 21:27:50 PDT
I ran into this bug when looking for a workaround for bug 275304.

After testing, it looks like presentation attribute (CSS) filters are only applied to the root SVG element. For context, the specification requires the filter attribute to apply to all graphics elements, <use>, and all containers except for <defs>.

The extent of this bug means there's no known workaround for bug 275304, rendering a large amount of SVG filter applications impossible to achieve in WebKit.

I've included a test case that demonstrates (A) that the filter presentation attribute fails when applied directly to a shape; (B) that it succeeds when applied to a root <svg> element; and (D) that there is no apparent workaround for applying a filter to external symbols (<use> referencing an external <symbol>).
Comment 5 tuanglen 2024-08-25 00:43:49 PDT
I created a minimal code sample to demonstrate the problem. It uses 2 <rect>s and 2 CSS rules. This problem causes interactive elements in a nice SVG interface that works well in Chrome and Firefox to be non-responsive when using Safari.

Here it is in a codepen: https://codepen.io/tuanglen/pen/eYwrXam

We can't just fall back to the fancier SVG <feComponentTransfer> that is supposedly the "equivalent" of CSS `filter: brightness()` because the results (on browsers that have both types of filters) look so much better with CSS's `filter: brightness()` than with SVG's `<feComponentTransfer>`. In Chrome and FF, smooth gradients remain smooth with `filter: brightness` but turn ugly and banded with `<feComponentTransfer>`. Ironically, `<feComponentTransfer>` in Safari handles gradients better than `<feComponentTransfer>` in Chrome or FF, but Safari needs the CSS filters such as `filter: brightness` to work, too.