I want to use svg filter as kind of texture for one of my svg objects, but there is one problem (which I didn't realize while working in Illustrator, because it rasterizes filters). The problem is that the svg filter scales with the size of svg itself (responsive web page so we don't know final svg size). And instead of the desired texture we can get that or that etc
Is there some workaround? Maybe with css vars and calc() or native svg features? And should I use some "query" for HDPI displays to make it little bit bigger (x-times)?
Here is snippet with fixed svg size with correct display (should look like the picture "desired"):
#wrap {
height: 2320px;
width: 2744px;
}
svg {
width: 41%;
}
<div id="wrap">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1232 1232">
<defs>
<filter height="100%" id="noise" width="100%" x="0%" y="0%">
<feTurbulence baseFrequency="0.75" numOctaves="5" stitchTiles="noStitch" type="fractalNoise"></feTurbulence>
<feDiffuseLighting lighting-color="#ccc" surfaceScale="17">
<feDistantLight azimuth="45" elevation="65"></feDistantLight>
</feDiffuseLighting>
</filter>
<style>
.a {
fill: #dedede;
filter:url(#noise);
}
</style>
</defs>
<title>-stackoverex</title>
<rect class="a" width="1232" height="1232"/>
</svg>
</div>
Let me try to clarify the situation.
There is a responsive block, the right side of which is occupied by a svg image, at different screen resolutions (or a browser zoom) block (and the image) must be scaled to fit the user's viewport.
The image is shown only on desktops starting from 992px
and its initial size is about 655x440
, it will increase somewhere up to 2620x1760
(if I'm not mistaken) on the PRO XDR display.
A significant part of the svg is occupied by a wall with a "plaster" texture, which should look realistic enough and it is too expensive to use a bitmap and even with the maximum avif compression the full-size texture will be too heavy.
Update:
so we can see how the texture should change (or not change) with various sizes @Kaiido
Here is a snippet with the desired result (Hi-res embedded image used) A cleaned original svg was used containing the wall and header basic markup. You can go to full page view and play with it as you want.
Maybe I was doing something wrong, but I still couldn't get rid of the texture tiling at some resolutions with "original filter", besides, some devices did not display that filter in the most correct way.
Also I can't find a way to scale down lighting
filters for small resolutions (if at all possible).
In fact, as a workaround, we can exclude the lighting
filters and use only the desaturated Turbulence
.
At resolutions less than 1400 or even more, it is visually quite similar and the filter itself is rendered much faster and is displayed correctly on all devices.
<filter id="stucco" height="100%" width="100%" x="0%" y="0%">
<feTurbulence baseFrequency="0.9" xresult="colorNoise" stitchTiles="stitch" numOctaves="90" type="fractalNoise" />
<feColorMatrix in="colorNoise" type="matrix" values=".33 .33 .33 0 0 .33 .33 .33 0 0 .33 .33 .33 0 0 0 0 0 1 0"/>
<feComposite operator="in" in2="SourceGraphic" result="monoNoise"/>
<feBlend in="SourceGraphic" in2="monoNoise" mode="multiply" />
</filter>
Not ideal, but acceptable, although there are some questions here too.
The first is that the filter lacks contrast (despite the "multiply" blending mode), the second is that for some reason media queries inside the svg styles do not work (although they should 1 2 etc) and it is impossible to adjust the baseFrequency for different resolutions and ratio> 1 (retina).
<svg>
<defs>
<style type="text/css">
@media (-webkit-min-device-pixel-ratio: 1) and (min-width:: 992px) {
#SVG-noise {
filter:url(#stucco-sm);
}
}
@media (-webkit-min-device-pixel-ratio: 1) and (min-width:: 1920px) {
#SVG-noise {
filter:url(#stucco-xl);
}
}
@media (-webkit-min-device-pixel-ratio: 2) and (min-width:: 992px) {
#SVG-noise {
filter:url(#stucco-hdpi);
}
}