web-platform-tests / interop

web-platform-tests Interop project
https://wpt.fyi/interop
319 stars 27 forks source link

The `filter()` function #717

Open thebabydino opened 2 months ago

thebabydino commented 2 months ago

Description

This allows us to apply a filter to an image before it's used as a background-image or border-image.

It has been in Safari for almost a decade now, but no other browser has followed. Basic test.

Even in Safari, it doesn't work for CSS gradients - 🪲 250303.

Sometimes we only want to apply a filter on an element's background-image or border-image-source, but not to the entire element.

For example, we may want to make a background-image semitransparent. With filter(), this is as simple as:

.my-elem {
    background: filter(url(balloon.jpg), opacity(.5)) 50%/ cover
}

Live demo (Safari only).

An element's background is made semi-transparent, so that we can see the hashed backdrop behind through it.

Otherwise, we have to create an absolutely positioned pseudo-element that covers its entire parent, move it behind any text content we may have. Finally we need to make the pseudo-element semitransparent. More code, plus we're using up a pseudo-element that we might need for something else.

.my-elem {
    position: relative
}

.my-elem::before {
    position: absolute;
    inset: 0;
    z-index: -1;
    background: url(balloon.jpg) 50%/ cover;
    opacity: .5;
    content: ''
}

Similarly, we may want to selectively desaturate a background-image. That is, considering our background-image is one with red roses we want an effect like that of the grayscale filter on everything but the red of the rose petals. Again, this is one line of CSS with filter() (live demo, Safari only), but we need to resort to a pseudo otherwise.

selective desaturation effect

Things get a bit more complicated when we want that pseudo to have a filtered image background layer which then gets blended with another background layer of the same pseudo and finally, the whole pseudo itself has a filter applied. This is the case if, starting from a random image, we want to turn it into its grayscale halftone dots version.

Live demo, Safari only. Without filter(), we'd need an extra element to achieve the same result.

Another situation is when we only want to a apply a filter to the border-image-source. For example, let's say we want the spaced out (with a padding area gap) border of an image to be a gradient that seems extracted out of the image palette. img elements can't have ::before/ ::after pseudos, so a no filter() solution would involve a wrapper. With filter(), we can do this by applying a large blur on the border-image-source and then an alpha correction. Live demo, Safari only.

screenshot of collection of images with such borders

Specification

Filter Effects Module Level 1

Additional Signals

No response

gsnedders commented 2 months ago

https://wpt.fyi/results/css/filter-effects/filter-function?label=experimental&label=master&aligned

foxt commented 2 months ago

what's the situation with filters like blur() where the area that the component visually takes up changes? would it clip to the box of the element (like backdrop-filter) or would it continue to expand the element (like filter)?

thebabydino commented 2 months ago

what's the situation with filters like blur() where the area that the component visually takes up changes? would it clip to the box of the element (like backdrop-filter) or would it continue to expand the element (like filter)?

No overflow, it's clipped.

GiandomenicoRiceputi commented 2 months ago

Super cool !!!!

thebabydino commented 2 months ago

Another use case for this would be to fix gradient banding using noise/ grain/ dither.

adactio commented 2 months ago

I just wanted to add a +1 and say that I had this exact use-case this week: I wanted to apply opacity to a background image (without having to mess around with using overlayed generated content instead).