Bug 250303
Summary: | The filter() function doesn't work with CSS gradients | ||
---|---|---|---|
Product: | WebKit | Reporter: | Ana Tudor <ana.tudor.lhnh> |
Component: | CSS | Assignee: | Tim Nguyen (:ntim) <ntim> |
Status: | RESOLVED FIXED | ||
Severity: | Normal | CC: | 50167214, ntim, webkit-bug-importer |
Priority: | P2 | Keywords: | InRadar |
Version: | WebKit Nightly Build | ||
Hardware: | Unspecified | ||
OS: | Unspecified | ||
See Also: | https://github.com/web-platform-tests/wpt/pull/37800 |
Ana Tudor
The following works:
```
background: filter(url(image.jpg), saturate(0))
```
But using a CSS gradient doesn't:
```
background: filter(linear-gradient(red, tan), saturate(0))
```
Live test: https://codepen.io/thebabydino/pen/RwxowwV
Per spec, the `filter()` function should accept a CSS gradient. It's defined as:
```
filter() = filter( [ <image> | <string> ], <filter-value-list> )
```
And `<image>` [includes CSS gradients](https://www.w3.org/TR/css-images-3/#image-values).
This could simplify things every time we need to add some kind of filter effect to a gradient - for example noise. We can apply an SVG `filter` on the element with the gradient we want to make grainy ([live demo](https://codepen.io/thebabydino/pen/abjpEbz/66e0409358289250d9d742124994e0de)), but applying a filter on an element also affects its text content, so in order to avoid that, we need to use up a pseudo-element, which we absolutely position underneath the element's text content and move the gradient `background` and the `filter` there. Which is totally doable and cross-browser, but it would be easier to only apply the filter on the gradient background.
Right now I have to do this ([live demo](https://codepen.io/thebabydino/pen/VwBPygQ/792799a12a8db65f739295179eca82bf)):
```
div { /* just the relevant CSS */
position: relative
}
div::before {
position: absolute;
inset: 0;
z-index: -1;
background: radial-gradient(circle, red, tan);
filter: url(#grainy);
content: '';
}
```
But it could be just this:
```
div { /* just the relevant CSS */
background: filter(radial-gradient(circle, red, tan), url(#grainy))
}
```
Attachments | ||
---|---|---|
Add attachment proposed patch, testcase, etc. |
Tim Nguyen (:ntim)
If I comment out these 2 lines, it seems to work: https://searchfox.org/wubkat/rev/c9fdb2c5fbdab38f8db4b0fe8a8f34f6801f2035/Source/WebCore/rendering/style/StyleGradientImage.cpp#191-192
Seems like a bug with StyleGradientImage::image().
Tim Nguyen (:ntim)
https://searchfox.org/wubkat/rev/c9fdb2c5fbdab38f8db4b0fe8a8f34f6801f2035/Source/WebCore/rendering/style/StyleCanvasImage.cpp#79 is also hit when using `filter()` with `-webkit-canvas()`
Tim Nguyen (:ntim)
I have a pretty straightforward fix for this.
Radar WebKit Bug Importer
<rdar://problem/104018718>
Tim Nguyen (:ntim)
Pull request: https://github.com/WebKit/WebKit/pull/8387
Tim Nguyen (:ntim)
Submitted web-platform-tests pull request: https://github.com/web-platform-tests/wpt/pull/37800
Tim Nguyen (:ntim)
Seems fixed (maybe by bug 283921 ?). I'll open a new PR to garden the tests.
Tim Nguyen (:ntim)
Pull request: https://github.com/WebKit/WebKit/pull/38475
EWS
Committed 288390@main (4890053fa297): <https://commits.webkit.org/288390@main>
Reviewed commits have been landed. Closing PR #38475 and removing active labels.
yisibl
Hi Tim, can you identify which version of Safari this was fixed in? This doesn't seem to be documented in any way.
Ana Tudor
Looks like it works from Safari 18.4 as per this thread https://fosstodon.org/@dbushell/114295597744892062