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..
Related
I am trying to place an arrow on the midpoint of the bezier curve. The solution using <animateMotion> in the question How properly shift arrow head on cubic bezier in SVG to its center , which moves a <path> which is the arrow and freezes it at the middle of the bezier curve, works only in Firefox. As the curve's points keep changing frequently in my case, I didn't want to use marker-mid as it is costly for me to calculate the midpoint of the bezier curve everytime.
<svg viewBox="0 0 500 500">
<g>
<path id="path1" d="M291.698 268.340 C321.698 268.340, 411.904 93.133 441.904 93.133"></path>
<path class="path_arrow" d="M0,0 L6,6 L0,12" transform="translate(-3,-6)">
<animateMotion dur="0s" rotate="auto" fill="freeze" keyTimes="0;1" keyPoints="0.5;0.5">
<mpath xlink:href="#path1"></mpath>
</animateMotion>
</path>
</g>
<g transform="translate(166.698,243.340)">
<circle r="5" class="p1"></circle>
</g>
<g transform="translate(441.904,68.133)" >
<circle r="5" class="p2"></circle>
</g>
</svg>
Is there any way to do this using CSS Animations so as to avoid using <animateMotion> ?
EDIT 1:
The endpoints of the curve here is draggable and so the points of the curve tend to change frequently. The animation is to move the arrow to the center of the curve without calculating the midpoints.
EDIT 2:
Thanks to Kaiido's comment, I added calcMode="linear" and the arrow is now placed on the path as expected. But When I reposition the end point by dragging, the arrow stays in its initial position(as shown) in Chrome but it is expected to move along the parent path. In Firefox this is working fine as before.
You could achieve the same with CSS offset-path, offset-distance and offset-rotate properties:
#path1 {
fill: none;
stroke: black;
}
.path_arrow {
transform: translate( -3px, -6px );
offset-path: path("M220 104C220 144,400 180,400 224");
offset-rotate: auto;
offset-distance: 50%;
}
body { background: white; }
<svg width="500" height="500" >
<path id="path1" d="M 220 104 C 220 144 400 180 400 224"
fill="none" stroke-width="2" stroke="black" />
<path class="path_arrow" d="M0,0 L0,12 L12,6 z" />
</svg>
But their browser support is far lower than the one of SMIL, so I wouldn't recommend it.
Note that I did fix the answer there where they were missing a calcMode="linear" attribute to make Blink browsers happy.
If you need IE support, you may want to try this js implementation which seems to support <animateMotion> and rotate, keeping in mind I didn't test it myself.
Regarding the question's "EDIT 2":
Chrome indeed seems to need an explicit call to update the <mpath>. This can be done by calling the beginElement() method of the <animationMotion> element after each update:
document.querySelector('svg').onmousemove = function(e) {
const rect = this.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
path1.setAttribute( 'd', `M ${x} ${y} C 220 144 400 180 400 224` );
// Chrome requires an explicit update
document.querySelector('animateMotion').beginElement();
}
<pre style="position: absolute;pointer-events:none">move your mouse to change the path</pre>
<svg width="500" height="500" >
<path id="path1" d="M 220 104 C 220 144 400 180 400 224"
fill="none" stroke-width="2" stroke="black" />
<path d="M0,0 L0,12 L12,6 z" transform="translate(-3,-6)">
<animateMotion dur="0s" rotate="auto" fill="freeze"
keyTimes="0;1" keyPoints="0.5;0.5" calcMode="linear" >
<mpath xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#path1"/>
</animateMotion>
</path>
</svg>
You have to use webkit animation inside the css. Also i would recommend https://codepen.io/collection/yivpx/. Is an open source project for SVG optimization. I also encourage you to name all your classes within your SVG in order to do cool CSS stuff with animate, like:
animation: kaboom 5s ease alternate infinite;
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 am new to svg and tried to replicate a simple mouseovereffect with inkscape, but my svg isnt doing a thing.
<svg xmlns="http://www.w3.org/2000/svg" width="74mm" height="105mm" viewBox="0 0 74 105">
<ellipse cx="37.042"
cy="244.461" rx="30.994" ry="24.568"
onmouseover=fill:"red";
onmouseout=fill"none";
opacity=".75" fill="#1a1a1a"
stroke="#000" stroke-width=".076"
stroke-linejoin="round"
paint-order="stroke markers fill"
transform="translate(0 -192)"/>
Can anybody tell me what i must put into the 2 fields of the inkscapeprogramm to make it work? I searched several hours but didnt find a matching solution.
I tried it with onmousein and fill:"red" and fill:"none" onmouseout but thats also not working.
many thanks in advance
onmouseover you want to change the style of the ellipse. Also as onmouseout you fill:noneyou need to add pointer-events:all for the ellipse to be able to interact with the mouse.
<svg xmlns="http://www.w3.org/2000/svg" width="74mm" height="105mm" viewBox="0 0 74 105">
<ellipse cx="37.042"
cy="244.461" rx="30.994" ry="24.568"
onmouseover="this.style.fill='red'";
onmouseout="this.style.fill='none'";
opacity=".75" fill="#1a1a1a"
stroke="#000" stroke-width=".076"
stroke-linejoin="round"
paint-order="stroke markers fill"
pointer-events="all"
transform="translate(0 -192)"/>
</svg>
I can't manage to animate a smooth transition between two similar <path />'s
There's this background effect I try to manage in my React app, where you have some blobs floating around that need to deform over time. I've created two blob shapes and tried to animate them via svg <animate /> tag but it only shifts momentarily from one shape to another after set dur property.
I've tried a few libraries like "react-spring" or react-something-svg (there's quite a stack of them out there) but the best I got was to have a path only morph animation with no fill or gradient properties.
Two shapes to shift between:
<svg>
<defs>
<radialGradient id="radialGradient827" cx="105.22" cy="144.2" r="51.989" gradientTransform="matrix(.23275 1.7456 -.93805 .12507 214.81 -67.26)" gradientUnits="userSpaceOnUse">
<stop stop-color="#00f" offset="0"/>
<stop stop-color="#00f3ff" offset="1"/>
</radialGradient>
</defs>
<g transform="translate(-67.756 -51.842)">
<path id="blob" transform="matrix(1.3569 0 0 1.3569 -2.3105 -31.738)" d="m52.019 88.923c1.008-6.2604 4.104-12.132 8.5366-16.666s10.166-7.7395 16.293-9.3701c12.256-3.2613 25.688-0.11296 36.296 6.8373 10.608 6.9503 18.58 17.4 24.228 28.755 5.6488 11.355 9.1245 23.653 12.182 35.961 3.0568 12.306 5.7394 24.802 6.0332 37.479 0.29383 12.677-1.9195 25.642-8.1354 36.694-3.1079 5.5261-7.1991 10.523-12.159 14.473-4.9595 3.9497-10.796 6.8358-17 8.1437s-12.77 1.0114-18.756-1.0776c-5.9861-2.089-11.361-5.9944-15.007-11.181-3.1833-4.5287-5.0021-9.9148-5.8599-15.383-0.85782-5.4687-0.79005-11.042-0.45735-16.567 0.6654-11.051 2.3656-22.3-0.18511-33.073-2.7384-11.566-10.084-21.385-16.303-31.514-3.1096-5.0645-5.9863-10.317-7.8786-15.95-1.8923-5.6336-2.7725-11.692-1.8278-17.56z" fill="url(#radialGradient827)" stroke-width="0"/>
</g>
</svg>
<svg>
<defs>
<radialGradient id="radialGradient827" cx="105.22" cy="144.2" r="51.989" gradientTransform="matrix(.23275 1.7456 -.93805 .12507 214.81 -67.26)" gradientUnits="userSpaceOnUse">
<stop stop-color="#00f" offset="0"/>
<stop stop-color="#00f3ff" offset="1"/>
</radialGradient>
</defs>
<g transform="translate(-60.376 -63.391)">
<path id="blob" transform="matrix(1.3569 0 0 1.3569 -2.3105 -31.738)" d="m52.019 88.923c5.9206-9.9143 16.696-16.529 28.107-18.297 11.411-1.7677 23.305 1.0814 33.237 6.9726 9.9318 5.8912 17.964 14.688 23.862 24.615 5.898 9.9278 9.7369 20.973 12.329 32.226 2.527 10.969 3.9032 22.276 3.0655 33.502-0.83773 11.225-3.9548 22.389-9.9198 31.935-5.965 9.5462-14.884 17.395-25.477 21.204s-22.841 3.3361-32.693-2.1096c-5.4164-2.9941-10.001-7.3752-13.622-12.394-3.6211-5.019-6.3053-10.669-8.3576-16.508-4.1048-11.677-5.7091-24.058-8.4789-36.122-2.4949-10.866-5.9526-21.549-7.3169-32.614-1.3643-11.065-0.45314-22.838 5.2631-32.41z" fill="url(#radialGradient827)" stroke-width="0"/>
</g>
</svg>
Here's a sandbox to play around: click here
I want to understand how to morph between two svg paths with a slow transition and having my gradient applied without using some specialized react animation library and incorporate it into my React app.
All I can do for now is to morph between to unstyled shapes using quite a few libraries and to shift from one shape to another momentarily
You can make the blobs preserve their final shape after the animation by specifying the fill property of the <animation> tag:
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 141 231" xmlns="http://www.w3.org/2000/svg" >
<radialGradient id="radialGradient827" cx="105.22" cy="144.2" r="51.989" gradientTransform="matrix(.23275 1.7456 -.93805 .12507 214.81 -67.26)" gradientUnits="userSpaceOnUse">
<stop stop-color="#00f" offset="0"/>
<stop stop-color="#00f3ff" offset="1"/>
</radialGradient>
<path id="blob" transform="translate(-60.376 -63.391) matrix(1.3569 0 0 1.3569 -2.3105 -31.738)" d="m52.019 88.923c5.9206-9.9143 16.696-16.529 28.107-18.297 11.411-1.7677 23.305 1.0814 33.237 6.9726 9.9318 5.8912 17.964 14.688 23.862 24.615 5.898 9.9278 9.7369 20.973 12.329 32.226 2.527 10.969 3.9032 22.276 3.0655 33.502-0.83773 11.225-3.9548 22.389-9.9198 31.935-5.965 9.5462-14.884 17.395-25.477 21.204s-22.841 3.3361-32.693-2.1096c-5.4164-2.9941-10.001-7.3752-13.622-12.394-3.6211-5.019-6.3053-10.669-8.3576-16.508-4.1048-11.677-5.7091-24.058-8.4789-36.122-2.4949-10.866-5.9526-21.549-7.3169-32.614-1.3643-11.065-0.45314-22.838 5.2631-32.41z" fill="url(#radialGradient827)" stroke-width="0">
<animate
attributeName="path"
to="m52.019 88.923c5.9206-9.9143 16.696-16.529 28.107-18.297 11.411-1.7677 23.305 1.0814 33.237 6.9726 9.9318 5.8912 17.964 14.688 23.862 24.615 5.898 9.9278 9.7369 20.973 12.329 32.226 2.527 10.969 3.9032 22.276 3.0655 33.502-0.83773 11.225-3.9548 22.389-9.9198 31.935-5.965 9.5462-14.884 17.395-25.477 21.204s-22.841 3.3361-32.693-2.1096c-5.4164-2.9941-10.001-7.3752-13.622-12.394-3.6211-5.019-6.3053-10.669-8.3576-16.508-4.1048-11.677-5.7091-24.058-8.4789-36.122-2.4949-10.866-5.9526-21.549-7.3169-32.614-1.3643-11.065-0.45314-22.838 5.2631-32.41z"
dur="1s"
fill="freeze" />
</path>
</svg>
NOTE: For the animation to work you need to ensure that both the initial and the final path have the same number of points, as detailed in here. Here's a great tool to make sure that the animation is possible.
On regards to your gradient, the browser should take care of that. You can simply apply it as you would on any other SVG file.
Avoiding JS libraries to deal with SVG animation is a great move, those tend to be bloated and messy. Stick to the official SVG specs whenever possible.
I'm trying to download some icons from http://game-icons.net/ and I need all black pixels to be transparent. All the techniques I've found on google have not worked, they have only turned them white.
Thanks for your time.
Am I missing something? Assuming you are using the SVG versions, why can't you just select the black rectangle and delete it?
Assuming for the moment you are correct, and perhaps it is some issue with importing the SVG into AI, it is easy enough to do it manually in a text editor.
Here are the contents of the "electric.svg" icon file:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="m0,0h512v512h-512z"/>
<g transform="matrix(15 0 0 15 -5924 -6649.4327)">
<use width="744.094" height="1052.362" transform="translate(432 440.36218)"/>
</g>
<g fill="#fff" transform="matrix(-3.75 0 0 3.75 2295.9997 -3330.35765)">
<path d="m512,944.3622 32,0 0-52 32,76-32,0 0,52z"/>
</g>
</svg>
http://jsfiddle.net/Hp8dT/
There is a <g> and a <use> in there that are not doing anything, so you could get rid of them if you like.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="m0,0h512v512h-512z"/>
<g fill="#fff" transform="matrix(-3.75 0 0 3.75 2295.9997 -3330.35765)">
<path d="m512,944.3622 32,0 0-52 32,76-32,0 0,52z"/>
</g>
</svg>
http://jsfiddle.net/Hp8dT/1/
The first <path> element is the one that is creating the black background, so just delete it. But in order for the lightning symbol (which is currently white) to be visible, we will need to change its colour. We'll use red.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<g fill="red" transform="matrix(-3.75 0 0 3.75 2295.9997 -3330.35765)">
<path d="m512,944.3622 32,0 0-52 32,76-32,0 0,52z"/>
</g>
</svg>
http://jsfiddle.net/Hp8dT/2/