One day I saw a few pictures shared by my friend Fish. I was attracted by their slight blur and the subtle glowing effects, and wondered what kind of filter function was used. But then she told me it's just because the camera lens wasn't wiped clean.

I really liked this effect, afterwards I tried to create it with CSS, mixing two identical images together with one of them blurred and semi-transparent.
Now I look back and find two other ways to do so.
Original image
I'll use this photo in the examples below, which was taken in the park last April.

Blend mode
In fact, all those methods are based on the concept of stacking multiple layers like in Photoshop.
The first method I mentioned above was to use a blurred layer on top of the original image,
and then merged them with mix-blend-mode
.


<picture>
<img src="url.png" />
<img src="url.png" class="blur" />
</picture>
<style>
picture {
position: relative;
display: block;
overflow: hidden;
}
picture .blur {
position: absolute;
inset: 0;
mix-blend-mode: normal;
filter: blur(3px) opacity(.5) brightness(1.3);
}
</style>
(I learned later from HN comments that the mix-blend-mode
is not needed.)
Backdrop filter
The backdrop-filter
property is quite special, it'll use its underneath layer as the filter source if the background of itself is transparent.
And it seems to be able to merge layers automatically. We could reduce one img
tag with this approach.

<picture>
<img src="url.png" />
</picture>
<style>
picture {
position: relative;
display: block;
}
picture::after {
content: '';
position: absolute;
inset: 0;
backdrop-filter: blur(3px) opacity(.5) brightness(1.3);
}
</style>
SVG filter
SVG filter is hard to understand for most people. But once you've learned how it works you'll see how straightforward it is.
Step 1
First we need to clone the source image and make it blurry with command feGaussianBlur
.
<filter>
<feGaussianBlur stdDeviation="3" />
</filter>
In SVG filter, each command will use the output of its previous command as input by default. The head command will use the element which it applies to as the source input. In this case, the original image.
Step 2
Continue to adjust the blurred result to make it semi-transparent and a little more bright.
By achieving that we use command feComponentTransfer
to modify its RGBA channel.
<filter>
<feGaussianBlur stdDeviation="3" />
<feComponentTransfer>
<feFuncR type="linear" slope="1.3" />
<feFuncG type="linear" slope="1.3" />
<feFuncB type="linear" slope="1.3" />
<feFuncA type="linear" slope=".5" />
</feComponentTransfer>
</filter>
Step 3
In the end, merge the transformed result with the original image by using command feBlend
.
<filter>
<feGaussianBlur stdDeviation="3" />
<feComponentTransfer>
<feFuncR type="linear" slope="1.3" />
<feFuncG type="linear" slope="1.3" />
<feFuncB type="linear" slope="1.3" />
<feFuncA type="linear" slope=".5" />
</feComponentTransfer>
<feBlend in2="SourceGraphic" />
</filter>
The feBlend
command accepts two sources, in2
and the omitted in
.
The original image is specified with SourceGraphic
, while the in
is passed by default
with the result of its previous command. Of course, we may also give each result a name, which would be more readable.
<filter>
<feGaussianBlur stdDeviation="3" result="blur" />
<feComponentTransfer in="blur" result="transformed">
<feFuncR type="linear" slope="1.3" />
<feFuncG type="linear" slope="1.3" />
<feFuncB type="linear" slope="1.3" />
<feFuncA type="linear" slope=".5" />
</feComponentTransfer>
<feBlend in="transformed" in2="SourceGraphic" />
</filter>
So there is the final result.

<img src="url.png" style="filter: url(#dreamy-blur)"/>
<svg height="0">
<filter id="dreamy-blur">
<feGaussianBlur stdDeviation="3" />
<feComponentTransfer>
<feFuncR type="linear" slope="1.3" />
<feFuncG type="linear" slope="1.3" />
<feFuncB type="linear" slope="1.3" />
<feFuncA type="linear" slope=".5" />
</feComponentTransfer>
<feBlend in2="SourceGraphic" />
</filter>
</svg>
Applying the effect
The above methods are basically only one that interpreted in different ways. The SVG filter is my favorite since it's most applicable.
I've used it once in one of my artwork.
#generative #CSS #SVG pic.twitter.com/aKEpsbqYKX
— yuanchuan (@yuanchuan23) May 27, 2022
Some camera effects will emerge together with the mask
property.
And I think there are more use cases.

.with-mask::after {
backdrop-filter: blur(5px) brightness(1.3);
mask: radial-gradient(circle at 50% 67%, #0006, #000 50%);
}