I am currently blurring images and using these as background whenever an image gets contained.
I am using the following svg filter with a filter spread out in two steps using feGaussianBlur and feColorMatrix. This renders perfectly in Chrome but in Safari and mobile browsers I see weird artefacts.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<filter
id="blurry"
width="150%"
height="150%"
x="-25%"
y="-25%"
colorInterpolationFilters="sRGB"
>
<feGaussianBlur stdDeviation="45" />
<feColorMatrix
type="matrix"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 10 0"
/>
<feGaussianBlur stdDeviation="45" />
<feColorMatrix
type="matrix"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 10 0"
/>
<feComposite in2="SourceGraphic" operator="in" />
</filter>
</svg>
Then in my CSS I use:
-webkit-filter: url('#blurry');
filter: url('#blurry');
Desired result (on desktop):
Result I got:
It shows these weird gaps..
Some things I've noticed:
Changing the filter size and position does not work
On some images I don't see these artefacts
Changing the filter stdDeviation does not work
Could it have something to do with the resolution of my images?
Those are big blurs - so Safari might be downscaling the filter resolution. Although it's deprecated and I think removed from Firefox and Chrome - you can try setting an explicit filterRes in your filter element because that's still supported in Safari.
(Also "colorInterpolationFilters" should be "color-interpolation-filters")
Related
This question already has answers here:
img src SVG changing the styles with CSS
(26 answers)
Closed 8 months ago.
I'm working on a frontendmentor challenge, and it came with a few svg files to use in the footer, and the last thing I need to do is make those svgs change color when you hover over them. Typically, I'd use filter:hue-rotate() but that only seems to work on some of the svg files, but not others.
For instance, if I have this html:
<footer>
<img src="./images/logo.svg">
<img src="./images/icon-facebook.svg">
</footer>
... and this CSS:
footer img {
filter:hue-rotate(90deg);
}
.. then the logo image gets color shifted but the facebook image does not. I'm able to view the contents of the svg images in VSCode, and they are a bit different, as the logo has a few components, while the facebook logo is much simpler. Here's the contents:
logo.svg:
<svg xmlns="http://www.w3.org/2000/svg" width="139" height="20">
<defs>
<linearGradient id="a" x1="72.195%" x2="17.503%" y1="0%" y2="100%">
<stop offset="0%" stop-color="#33D35E" />
<stop offset="100%" stop-color="#2AB6D9" />
</linearGradient>
</defs>
<g fill="none" fill-rule="evenodd">
<path fill="#2D314D" fill-rule="nonzero"
d="M37.754 15.847c2.852 0 5.152-1.622 5.952-4.216h-3.897c-.376.665-1.14 1.066-2.055 1.066-1.237 0-2.065-.674-2.32-1.978h8.44c.051-.352.081-.694.081-1.037 0-3.335-2.537-5.95-6.201-5.95-3.568 0-6.175 2.564-6.175 6.049 0 3.473 2.628 6.066 6.175 6.066zm2.344-7.297h-4.596c.317-1.129 1.11-1.749 2.252-1.749 1.181 0 2 .613 2.344 1.75zm10.946 7.296c1.32 0 2.5-.434 3.43-1.188l.336.804h3.027V4.093h-2.919l-.4.88c-.94-.775-2.135-1.222-3.474-1.222-3.476 0-5.961 2.505-5.961 6.026 0 3.533 2.485 6.07 5.961 6.07zm.524-3.467c-1.467 0-2.545-1.108-2.545-2.593 0-1.475 1.069-2.583 2.545-2.583 1.466 0 2.544 1.108 2.544 2.583 0 1.485-1.078 2.593-2.544 2.593zm13.123 3.467c3.02 0 5.025-1.554 5.025-3.93 0-2.883-2.387-3.256-4.183-3.575-1.08-.193-1.95-.344-1.95-.99 0-.527.422-.838 1.05-.838.71 0 1.197.337 1.197 1.063h3.667c-.044-2.303-1.92-3.843-4.816-3.843-2.912 0-4.854 1.47-4.854 3.75 0 2.757 2.337 3.289 4.1 3.574 1.092.181 1.952.368 1.952 1.024 0 .587-.543.88-1.116.88-.742 0-1.32-.383-1.32-1.214h-3.77c.036 2.463 1.919 4.1 5.018 4.1zm8.1 3.858c2.936 0 4.344-1.257 5.877-4.736l4.764-10.863h-4.206l-2.249 6.263-2.412-6.263H70.31l4.698 10.43c-.53 1.414-.983 1.804-2.48 1.804H71.45v3.365h1.341zm18.504-3.858c3.5 0 5.973-2.515 5.973-6.048S94.796 3.75 91.295 3.75a5.332 5.332 0 00-2.825.784V0H84.6v15.474h2.897l.37-.844c.923.771 2.102 1.216 3.428 1.216zm-.523-3.467c-1.467 0-2.545-1.108-2.545-2.58 0-1.486 1.078-2.594 2.545-2.594 1.466 0 2.544 1.108 2.544 2.593 0 1.473-1.087 2.58-2.544 2.58zm13.598 3.467c1.32 0 2.5-.434 3.43-1.188l.336.804h3.027V4.093h-2.918l-.401.88c-.939-.775-2.135-1.222-3.474-1.222-3.476 0-5.96 2.505-5.96 6.026 0 3.533 2.484 6.07 5.96 6.07zm.524-3.467c-1.467 0-2.545-1.108-2.545-2.593 0-1.475 1.07-2.583 2.545-2.583 1.467 0 2.545 1.108 2.545 2.583 0 1.485-1.078 2.593-2.545 2.593zm12.653 3.095V9.403c0-1.447.702-2.3 1.923-2.3.986 0 1.483.657 1.483 1.98v6.39h3.915V8.543c0-2.897-1.733-4.773-4.373-4.773-1.47 0-2.733.565-3.58 1.508l-.537-1.172h-2.747v11.369h3.916zm13.748 0v-4.808l2.848 4.808h4.616l-3.902-5.95 3.543-5.419h-4.397l-2.708 4.454V0h-3.916v15.474h3.916z" />
<g fill="url(#a)">
<path d="M10.802 0L0 19.704h5.986L16.789 0z" />
<path opacity=".5" d="M18.171 0L7.368 19.704h5.986L24.157 0z" />
<path opacity=".15" d="M25.539 0L14.737 19.704h5.986L31.525 0z" />
</g>
</g>
</svg>
icon-facebook.svg:
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
<path fill="#FFF"
d="M18.896 0H1.104C.494 0 0 .494 0 1.104v17.793C0 19.506.494 20 1.104 20h9.58v-7.745H8.076V9.237h2.606V7.01c0-2.583 1.578-3.99 3.883-3.99 1.104 0 2.052.082 2.329.119v2.7h-1.598c-1.254 0-1.496.597-1.496 1.47v1.928h2.989l-.39 3.018h-2.6V20h5.098c.608 0 1.102-.494 1.102-1.104V1.104C20 .494 19.506 0 18.896 0z" />
</svg>
So the question is, what's the technical difference in why logo can utilize css filters but facebook cannot? And ultimately, what's the solution here to make the facebook logo change colors when hovered? Using fill:#f00 doesn't seem to work either as I can't target the inner svg components since its a file.
Note: I could create a 2nd image and color it differently and swap between them, or I could extract the inner svg stuff and insert that into the page instead, but I'm really trying to understand/solve the .svg file problem. Or at least verify 100% that it can't be done.
Note2: StackOverflow showed me another similar question (similar, but NOT THE SAME), and the answer there was that you can't affect svg file color/fill with CSS only inline SVG elements. Ok, noted, but what about CSS filters? They seem to work on the logo image but not the Facebook image, so why is that? What's the main thing there that's causing it work on one but not the other.
When I use this in my css, I can make the facebook logo any color I want:
footer img:hover {
background-color: *Any color you want it to be*;
}
But the point is, this works well for the Facebook logo but not for the first logo..
background-image: url("data:image/svg+xml,%3csvg
xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'
fill='%23ffffff'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0
1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708
0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") !important;
Currently this uses external icon. I need to use a specific image from my local - /images/icon/svg which changes colors on multiple features. so want to change through fill option.
How can I update the URL to get both fill and image URL?
You can do two things :
Download that SVG (in SVG format only ) and define its path on the background and manipulate its color through CSS.
you can change the try to change the "fill" prop in the URL it self.
in the footer of my site I have social icons as SVGs that fill depending on screen size and hover state.
One example is for instagram:
HTML:
<a href="https://www.instagram.com/pacific_beach_homes/" title="Visit our Instagram page" target="blank" >
<svg class="instagram" alt="Instagram icon" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Instagram</title>
<defs>
<linearGradient id="ig-gradient">
<stop offset="0%" stop-color="#F8ED34" />
<stop offset="50%" stop-color="#EA118D" />
<stop offset="100%" stop-color="#2E368F" />
</linearGradient>
</defs>
<path d="M12 0C8.74 0 8.333.015 7.053.072 5.775.132 4.905.333 4.14.63c-.789.306-1.459.717-2.126 1.384S.935 3.35.63 4.14C.333 4.905.131 5.775.072 7.053.012 8.333 0 8.74 0 12s.015 3.667.072 4.947c.06 1.277.261 2.148.558 2.913.306.788.717 1.459 1.384 2.126.667.666 1.336 1.079 2.126 1.384.766.296 1.636.499 2.913.558C8.333 23.988 8.74 24 12 24s3.667-.015 4.947-.072c1.277-.06 2.148-.262 2.913-.558.788-.306 1.459-.718 2.126-1.384.666-.667 1.079-1.335 1.384-2.126.296-.765.499-1.636.558-2.913.06-1.28.072-1.687.072-4.947s-.015-3.667-.072-4.947c-.06-1.277-.262-2.149-.558-2.913-.306-.789-.718-1.459-1.384-2.126C21.319 1.347 20.651.935 19.86.63c-.765-.297-1.636-.499-2.913-.558C15.667.012 15.26 0 12 0zm0 2.16c3.203 0 3.585.016 4.85.071 1.17.055 1.805.249 2.227.415.562.217.96.477 1.382.896.419.42.679.819.896 1.381.164.422.36 1.057.413 2.227.057 1.266.07 1.646.07 4.85s-.015 3.585-.074 4.85c-.061 1.17-.256 1.805-.421 2.227-.224.562-.479.96-.899 1.382-.419.419-.824.679-1.38.896-.42.164-1.065.36-2.235.413-1.274.057-1.649.07-4.859.07-3.211 0-3.586-.015-4.859-.074-1.171-.061-1.816-.256-2.236-.421-.569-.224-.96-.479-1.379-.899-.421-.419-.69-.824-.9-1.38-.165-.42-.359-1.065-.42-2.235-.045-1.26-.061-1.649-.061-4.844 0-3.196.016-3.586.061-4.861.061-1.17.255-1.814.42-2.234.21-.57.479-.96.9-1.381.419-.419.81-.689 1.379-.898.42-.166 1.051-.361 2.221-.421 1.275-.045 1.65-.06 4.859-.06l.045.03zm0 3.678c-3.405 0-6.162 2.76-6.162 6.162 0 3.405 2.76 6.162 6.162 6.162 3.405 0 6.162-2.76 6.162-6.162 0-3.405-2.76-6.162-6.162-6.162zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm7.846-10.405c0 .795-.646 1.44-1.44 1.44-.795 0-1.44-.646-1.44-1.44 0-.794.646-1.439 1.44-1.439.793-.001 1.44.645 1.44 1.439z"/></svg>
</a>
CSS:
.instagram {
fill: #fe4164;
fill: url('#ig-gradient');
}
I included a backup color above the fill:url(...) because I thought this might fix it if Safari doesn't accept gradient fills. But that is not the problem. It seems that safari is actually changing the url from what is typed in the css file.
On most browsers, the fill: url(#ig-gradient); is working fine. However Safari for iOS is different. . .
Safari for iOS is changing the fill url to a full url link: url(https://pacificbeachhomes.com/wp-content/themes/pacificbeachhomes/#ig-gradient) which doesnt work, instead of url(#ig-gradient) which works. .. .
Anyone know why safari for iOS is adding the domain? I tried putting the fill url in quotes (shown above) and without quotes and it doesnt seem to change.
active site is: pacificbeachhomes.com
I need to change color of icon on hover from gray(#b7b7b7) to coral(#b45d64).
I found out that make gray color from coral using CSS filter pretty easy. So for now I use reverse solution, change color of all icons to coral in Photoshop and set CSS filter to gray, as in below code example and on hover disable CSS filter using none value.
But I wonder is there any algorithm or way to get particular color like #b45d64 from gray. I used sepia and play manually with brightness, saturate, and hue-rotate filters, but I there an easier way to do this (I mean easier way to calculate brightness, saturate, and hue-rotate to get #b45d64 from gray using sepia)?
.makegray:hover{
-webkit-filter: brightness(1.72) saturate(0) hue-rotate(0deg);
filter: brightness(1.72) saturate(0) hue-rotate(0deg);
}
.makecoral:hover{
-webkit-filter: sepia(1) brightness(0.54) saturate(2) hue-rotate(305deg);
filter: sepia(1) brightness(0.54) saturate(2) hue-rotate(305deg);
}
<img src="http://dummyimage.com/200x200/b7b7b7/fff.png&text=hsla(0,00x25,720x25)" class="makecoral" alt=""><br>
<img src="http://dummyimage.com/200x200/b45d64/fff.png&text=hsl(355,+370x25,+540x25)" class="makegray" alt="">
If you reference an SVG filter from your CSS, then you can get a specific color. SVG filter snippet below. For your specific color replace the .7/.4/.5 with the unitized value of your RGB values.
<filter id="colorme" color-interpolation-filters="sRGB">
<feColorMatrix type="matrix" values="0 0 0 0 .7 0 0 0 0 .4 0 0 0 0 .5 0 0 0 1 0"/>
</filter>
Here's a jsfiddle of what I have so far: https://jsfiddle.net/tcetcvmu/
Notice how the lower path has a large yellow glow, but the upper path does not. I believe this is because the lower path has a bounding box that mostly encompasses the yellow glow, but the upper path has a small bounding box that does not encompass where the yellow glow would be.
I'd like to expand the bounding box so that the upper path has a glow as well. Ideally, I'd like to do this outside of the path definition, as the paths are programmatically generated.
HTML code:
<svg>
<filter id="outline_selected" x="-50%" y="-50%" width="200%" height="200%">
<feMorphology result="offset" in="SourceGraphic" operator="dilate" radius="3"/>
<feColorMatrix result="drop" in="offset" type="matrix"
values="1 1 1 1 1
1 1 1 1 1
0 0 0 0 0
0 0 0 1 0" />
<feBlend in="SourceGraphic" in2="drop" mode="normal" />
</filter>
<path class="individual" d="M256.5,29.5625C369.75,29.5625 369.75,29.5625 483,29.5625L483,30.5625C369.75,30.5625 369.75,30.5625 256.5,30.5625Z" style="stroke-width: 1px;"></path>
<path class="individual" d="M256.5,216.9375C369.75,216.9375 369.75,276.0625 483,276.0625L483,277.0625C369.75,277.0625 369.75,217.9375 256.5,217.9375Z" style="stroke-width: 1px;"></path>
</svg>
CSS:
.individual {
fill: rgba(255, 0, 0, 1);
filter:url(#outline_selected);
}
svg {
width: 500px;
height: 500px;
}
if you need a filter on such a straight line, use a rect with a height 1px, and only make the filter region as large as needed. If your straight 1px heigh line(rect) needs 3px radius from Morphology us small width and x avlues for your filter region and y="-100%" height="300%"
<svg width="200" height="200" viewBox="0 0 100 100">
<filter id="outline_selected" x="-1%" y="-100%" width="102%" height="300%">
<feMorphology result="offset" in="SourceGraphic" operator="dilate" radius="3"/>
<feColorMatrix result="drop" in="offset" type="matrix"
values="1 1 1 1 1
1 1 1 1 1
0 0 0 0 0
0 0 0 1 0" />
<feBlend in="SourceGraphic" in2="drop" mode="normal" />
</filter>
<rect x="5" y="50" width="90" height="1" filter="url(#outline_selected)"/>
</svg>
It's many years later, but I am running into a similar issue, and here is what I have found. Using a rectangle won't work since you clearly want to use curved paths.
The filter units are set to the objectBoundingBox by default. In the case of the first line, the height of the bounding box is very small, and even a 300% height is not enough to encompass the full filter you have. It's very slightly tilted, its actually not height 0. If it were exactly 0, you wouldn't see any effect at all since even 300% of the height would be 0. So this wouldn't even work at all with straight vertical or straight horizontal paths.
You could set filterUnits prop of the filter to 'userSpaceOnUse' instead, and you wouldn't need the coords/dims either.
However, userSpaceOnUse sets the coordinates at the time that the filter is referenced. So if you apply a transform later to a parent element, you may end up cropping the effect.
The best solution, I think, is to wrap each of your paths in a element and apply the filter on the instead. And then, add some invisible object to the , sibling to your path which will expand the bounding box of the g beyond just the path. You could add an invisible 90% rotated (around center) version of your path. Or simply a path with a bunch of "M"s in it's d prop that moves around to create a larger bounding box. There are a lot of options here, but the idea is to have some non-visible object with a bounding box that is as big as you want your filter to encompass. It depends on how your paths are being generated what is easier to do.
quick fix:
<filter id="outline_selected" filterUnits = 'userSpaceOnUse'>
But this may run into cropping issues depending on if you use transforms above this element after it has already been rendered.