SVG filter not visible when using custom viewBox - css

Why is setting an svg viewBox to say 0 0 1 1 causing my filter to disappear? I also tried playing around with x, y, height, and width attributes as well as changing primitiveUnits attribute, nothing did work. Any help would be appreciated.
svg {
border: 1px solid red;
height: 100px;
width: 100px;
}
svg circle {
fill: black;
}
<html>
<body>
<svg viewBox="0 0 1 1">
<defs>
<filter id="halo1">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>
<circle cx="50%" cy="50%" r="25%" filter="url(#halo1)"></circle>
</svg>
<svg>
<defs>
<filter id="halo2">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>
<circle cx="50%" cy="50%" r="25%" filter="url(#halo2)"></circle>
</svg>
</body>
</html>
Fiddle playground: https://jsfiddle.net/6x34urzg/14/

When the image is scaled from 1x1 (the viewBox="0 0 1 1") to 100x100 px the standard deviation (stdDeviation="3") is also scaled. The circle with the filter is still there but 100 time too big.
If you set the standard deviation to 1/100 (stdDeviation=".03") you will get the same result as the other SVG.
svg {
border: 1px solid red;
height: 100px;
width: 100px;
}
svg circle {
fill: black;
}
<html>
<body>
<svg viewBox="0 0 1 1">
<defs>
<filter id="halo1">
<feGaussianBlur in="SourceGraphic" stdDeviation=".03" />
</filter>
</defs>
<circle cx="50%" cy="50%" r="25%" filter="url(#halo1)"></circle>
</svg>
<svg>
<defs>
<filter id="halo2">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>
<circle cx="50%" cy="50%" r="25%" filter="url(#halo2)"></circle>
</svg>
</body>
</html>

Actually, in the CSS you know insert CSS to HTML like Internal CSS and Inline CSS. Internal CSS is you write css on in inside on tag and that tend general for use to give style on SVG. While, Inline CSS used to write css on unique element on tags like your program(coding). Although you have writenn css svg, your svg on "Hallo1" disappear because your program have write inline CSS viewBox="0 0 1 1"make your svg "Halo 1" disappear. Moreover, viewBox="0 0 1 1" make your circle dissapear because weight=1 and height=1 so that cirle which resulted so small and you cannot see that. To solve that problem you can change your viewBox become 'viewBox="0 0 100 100" '

Related

How to use SVG clipPath with Pattern via CSS clip-path property?

The initial SVG figure with pattern:
<svg width="200" height="200" viewBox="0 0 100 100">
<defs>
<pattern id="img-dotted-dots" x="0" y="0" height=".08" width="7.69%">
<circle cx="2" cy="2" fill="white" r="0.8"></circle>
</pattern>
<mask id="img-dotted-mask">
<rect width="100" height="100" fill="url(#img-dotted-dots)"></rect>
</mask>
</defs>
<path d="M0 0 H 100 V 100 H 0 Z" mask="url(#img-dotted-mask)" fill="#1063B1"></path>
</svg>
Need to achieve:
One instance of the SVG figure with pattern for refferencing with CSS as clip-path.
I have tried to create SVG clipPath element and bind to CSS clip-path by this way
.figure {
width: 300px;
height: 300px;
clip-path: url(#img-dotted-clip-path);
background-color: #1063B1;
}
<div class="figure"></div>
<svg width="0" height="0" viewBox="0 0 100 100">
<defs>
<clipPath
clipPathUnits="objectBoundingBox"
id="img-dotted-clip-path">
<pattern
patternUnits="objectBoundingBox"
patternContentUnits="objectBoundingBox"
x="0" y="0" height="0.1" width="0.1">
<circle cx="0" cy="0" fill="white" r="0.5"></circle>
</pattern>
</clipPath>
</defs>
</svg>
Nothing happens.
Expected result - the same as the previous snippet.
For comparing:
If I use SVG rect - CSS clip-path works.
If pattern - doesn't
.figure {
width: 300px;
height: 300px;
clip-path: url(#img-dotted-clip-path);
background-color: #1063B1;
}
<div class="figure"></div>
<svg width="0" height="0" viewBox="0 0 100 100">
<defs>
<clipPath
clipPathUnits="objectBoundingBox"
id="img-dotted-clip-path">
<rect width="1" height="1"></rect>
</clipPath>
</defs>
</svg>
The only things that are valid inside a clip path are:
Shape elements (‘circle’, ‘ellipse’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’)
‘text’
‘use’
Plus you can use animation elements etc to animate the clip path. However, only the shapes of those elements are used. Effects such as patterns, filters, etc are ignored.
The only way you could get the effect you want to work as a clipping path would be to add numerous <circle> elements to your <clipPath>.
<clipPath>
<circle>
<circle>
<circle>
<circle>
... etc ...
</clipPath>
But you could use a mask instead. Masks allow patterns.
.figure {
width: 300px;
height: 300px;
-webkit-mask: url(#img-dotted-mask);
mask: url(#img-dotted-mask);
background-color: #1063B1;
}
<p>This only works in Firefox</p>
<div class="figure"></div>
<svg width="0" height="0">
<defs>
<pattern id="img-dotted-pattern"
viewBox="0 0 1 1"
patternUnits="userSpaceOnUse" x="0" y="0" width="20" height="20">
<rect width="1" height="1" fill="black"/>
<circle cx="0.5" cy="0.5" fill="white" r="0.15"></circle>
</pattern>
<mask id="img-dotted-mask">
<rect width="2000" height="2000" fill="url(#img-dotted-pattern)"/>
</mask>
</defs>
</svg>
However inline SVG masks applied to HTML elements, like my example above, only work in Firefox. To get an SVG mask to work in Chrome, you would need to use mask or mask-image with an external or Data URL (as Temani has done in their answer).
You can recreate the same thing using mask combined with radial-gradient
.figure {
width: 300px;
height: 300px;
background:linear-gradient(to right,red,#1063B1);
/*radius here size here*/
-webkit-mask:radial-gradient(3px, #fff 97%,transparent 100%) 0 0/20px 20px;
mask:radial-gradient(3px, #fff 97%,transparent 100%) 0 0/20px 20px;
}
body {
background:#f2f2f2;
}
<div class="figure"></div>
Or consider the SVG inside the mask property. Make sure to escape the # and correctly set the viewbox and width/height to have a perfect repeat
.figure {
width: 300px;
height: 300px;
background:linear-gradient(to right,red,#1063B1);
-webkit-mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200" height="192" viewBox="0 0 100 90"><defs><pattern id="img-dotted-dots" x="0" y="0" height=".08" width="7.69%"><circle cx="2" cy="2" fill="white" r="0.8"></circle></pattern><mask id="img-dotted-mask"><rect width="100" height="100" fill="url(%23img-dotted-dots)"></rect></mask></defs><path d="M0 0 H 100 V 100 H 0 Z" mask="url(%23img-dotted-mask)" fill="%231063B1"></path></svg>');
mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200" height="192" viewBox="0 0 100 90"><defs><pattern id="img-dotted-dots" x="0" y="0" height=".08" width="7.69%"><circle cx="2" cy="2" fill="white" r="0.8"></circle></pattern><mask id="img-dotted-mask"><rect width="100" height="100" fill="url(%23img-dotted-dots)"></rect></mask></defs><path d="M0 0 H 100 V 100 H 0 Z" mask="url(%23img-dotted-mask)" fill="%231063B1"></path></svg>');
}
body {
background:#f2f2f2;
}
<div class="figure"></div>

SVG filter from another invisible SVG removes target completely

So I have 2 SVG elements at my page: one with path and another with filter (I made this to be able to apply that filter to multiple SVGs
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 1 1 " class="filter-target">
<path filter="url(#glow)" d="M 0,0 v 1 h 1 v-1 h-1 z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1 1" class="filter-source">
<defs>
<filter id="glow">
<feFlood flood-color="rgb(0,0,255)" in="SourceAlpha" result="makeBlue" />
<feMerge>
<feMergeNode in="makeBlue"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
</svg>
Everything was ok but then I decided to hide second SVG to prevent layout issues. So I made the following CSS:
.filter-source {
display: none;
}
.filter-target {
width: 40px;
height: 40px;
border: 1px red dashed;
}
As a result, path with filter attribute disappeared too, just like browser removed second SVG completely instead hiding.
Got the same effect at Chrome 76 and Firefox 60 under Linux.
Is it a bug or spec?
Fiddle is here
The filter inherits the property display: none, so nothing is displayed in the visible svg. I think you should remove the .filter-source css code and simply add width="0" height="0" to the second svg:
.filter-target {
width: 40px;
height: 40px;
border: 1px red dashed;
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 1 1 " class="filter-target">
<path filter="url(#glow)" d="M 0,0 v 1 h 1 v-1 h-1 z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1 1" class="filter-source" width="0" height="0">
<defs>
<filter id="glow">
<feFlood flood-color="rgb(0,0,255)" in="SourceAlpha" result="makeBlue" />
<feMerge>
<feMergeNode in="makeBlue"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
</svg>
Now the layout is not interrumpted
EDIT after comments
Why path stays visible when I return display:none back?
This is a question about browser behavior. I see it happens in Chrome, but not in Firefox. Obviously, the correct behavior is that of Firefox.
documentation you referenced says "it does not prevent elements from being referenced by other elements"
The element is being referenced, but its display property is none, and that is why you see no color. You are applying an invisible filter.
display property is not inherited
The third paragraph of the document reads:
When applied to a container element, setting display to none causes the
container and all of its children to be invisible; thus, it acts on groups
of elements as a group. This means that any child of an element with
display="none" will never be rendered even if the child has a value for
display other than none.
Bear in mind that we are talking about svg display, rather than css display.

Viewbox placement in referencing SVG symbols and CSS dimensions

I edited my initial cry of despair into something more to the technical point, in order to turn it into a Q&A.
I'm using SVG symbols that I reference in the document with use elements. I'm styling these with CSS. I don't want to set both height and width in the CSS, I want to set only one of them with the other one scaling accordingly.
I do set a viewBox attribute on the symbol. But the graphic does not scale correctly.
<!DOCTYPE html>
<html>
<head>
<title>SVG Symbols</title>
<style>
body { margin: 20px; }
.svg-large { width: 500px; fill: yellow;}
</style>
</head>
<body>
<svg style="display:none;">
<symbol id="scary-smiley" viewBox="0 0 20 20">
<circle cx="10" cy="10" r="9.5" stroke-width="1"
stroke="black" />
<circle cx="6" cy="7" r="1.5" fill="black"/>
<circle cx="14" cy="7" r="1.5" fill="black"/>
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Teeth_by_David_Shankbone.jpg/320px-Teeth_by_David_Shankbone.jpg"
width="10" height="5.2" x="5" y="11"/>
</symbol>
</svg>
<svg class="svg-large">
<use xlink:href="#scary-smiley"/>
</svg>
</body>
</html>
The code below has been tested in current Firefox, Chrome and a Webkit-based browser named Midori.
For some reason, defining the viewBox on the symbol element does not have the full desired effect in Firefox and Chrome. It does have some effect, though, as it makes the element scaleable. So, if you want set both width and height in CSS, you can do that.
If the viewBox element is specified only on the symbol and you set only one of width or height, then in Firefox and Chrome the other dimension is set according the default object size in HTML 5 whis is 300x150 px. So, in the example in the question, you get a 500x150 px element and the graphic is scaled to fit that rectangle.
If you want to define only one width or height with the other one scaling accordingly, then defining viewBox on the referencing SVG element works:
<!DOCTYPE html>
<html>
<head>
<title>SVG Symbols</title>
<style>
body { margin: 20px; }
.svg-large { width: 500px; fill: yellow;}
</style>
</head>
<body xmlns:xlink="http://www.w3.org/1999/xlink">
<svg style="display:none;">
<symbol id="scary-smiley">
<circle cx="10" cy="10" r="9.5" stroke-width="1"
stroke="black" />
<circle cx="6" cy="7" r="1.5" fill="black"/>
<circle cx="14" cy="7" r="1.5" fill="black"/>
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Teeth_by_David_Shankbone.jpg/320px-Teeth_by_David_Shankbone.jpg"
width="10" height="5.2" x="5" y="11"/>
</symbol>
</svg>
<svg class="svg-large" viewBox="0 0 20 20">
<use xlink:href="#scary-smiley"/>
</svg>
</body>
</html>
Firefox' and Chrome's behaviour is standard compliant, according to the SVG 2 specification, according to which the <svg><use .../></svg> clause establishes a new SVG viewport.

Animated growing arrow link

Hi, I was wondering how one would go about animating an svg arrow like above (on hover).
I have tried playing around with CSS transforms, but they also scale the arrow-head which is no good. I assume the correct way to do this is using SVGs animations, but I don't know where to start.
For example I would the following arrow (line only) to grow and arrow head to move accordingly.
<svg width="600px" height="100px">
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#f00" />
</marker>
</defs>
<line x1="50" y1="50" x2="100" y2="50" stroke="#000" stroke-width="5" marker-end="url(#arrow)" />
</svg>
Any help is very much appreciated!
You can create growing arrow by using "respoinsive" SVG like this.
svg{
width: 20px;
height: 20px;
transition:width 2s ease;
overflow: visible;
}
svg:hover{
width: 100px;
}
<svg>
<defs>
<marker id="m" markerWidth="4" markerHeight="8"
refX="0" refY="1" viewBox="0 0 1 2">
<polygon points="0,0 1,1 0,2" fill="black"/>
</marker>
</defs>
<line x1="0" y1="50%" x2="100%" y2="50%"
stroke-width="2" marker-end="url(#m)" stroke="black"/>
</svg>
There are some points to implement.
svg has no viewBox (so it is "responsive" SVG).
Line of arrow is defined by relative position of (root) svg size.
Arrow head is defined by marker element.
Growing animation is defined by CSS transition which animate width of svg. So, arrow grows with svg size.
In order to animate the individual SVG elements like HTML elements, you'll need to embed the SVG directly into the page like this:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="612px" height="502.174px" viewBox="0 65.326 612 502.174" enable-background="new 0 65.326 612 502.174"
xml:space="preserve" class="logo">
<ellipse class="ground" cx="283.5" cy="487.5" rx="259" ry="80"/>
<path class="kiwi" d="M210.333,65.331C104.367,66.105-12.349,150.637,1.056,276.449c4.303,40.393,18.533,63.704,52.171,79.03
c36.307,16.544,57.022,54.556,50.406,112.954c-9.935,4.88-17.405,11.031-19.132,20.015c7.531-0.17,14.943-0.312,22.59,4.341
c20.333,12.375,31.296,27.363,42.979,51.72c1.714,3.572,8.192,2.849,8.312-3.078c0.17-8.467-1.856-17.454-5.226-26.933
c-2.955-8.313,3.059-7.985,6.917-6.106c6.399,3.115,16.334,9.43,30.39,13.098c5.392,1.407,5.995-3.877,5.224-6.991
c-1.864-7.522-11.009-10.862-24.519-19.229c-4.82-2.984-0.927-9.736,5.168-8.351l20.234,2.415c3.359,0.763,4.555-6.114,0.882-7.875
c-14.198-6.804-28.897-10.098-53.864-7.799c-11.617-29.265-29.811-61.617-15.674-81.681c12.639-17.938,31.216-20.74,39.147,43.489
c-5.002,3.107-11.215,5.031-11.332,13.024c7.201-2.845,11.207-1.399,14.791,0c17.912,6.998,35.462,21.826,52.982,37.309
c3.739,3.303,8.413-1.718,6.991-6.034c-2.138-6.494-8.053-10.659-14.791-20.016c-3.239-4.495,5.03-7.045,10.886-6.876
c13.849,0.396,22.886,8.268,35.177,11.218c4.483,1.076,9.741-1.964,6.917-6.917c-3.472-6.085-13.015-9.124-19.18-13.413
c-4.357-3.029-3.025-7.132,2.697-6.602c3.905,0.361,8.478,2.271,13.908,1.767c9.946-0.925,7.717-7.169-0.883-9.566
c-19.036-5.304-39.891-6.311-61.665-5.225c-43.837-8.358-31.554-84.887,0-90.363c29.571-5.132,62.966-13.339,99.928-32.156
c32.668-5.429,64.835-12.446,92.939-33.85c48.106-14.469,111.903,16.113,204.241,149.695c3.926,5.681,15.819,9.94,9.524-6.351
c-15.893-41.125-68.176-93.328-92.13-132.085c-24.581-39.774-14.34-61.243-39.957-91.247
c-21.326-24.978-47.502-25.803-77.339-17.365c-23.461,6.634-39.234-7.117-52.98-31.273C318.42,87.525,265.838,64.927,210.333,65.331
z M445.731,203.01c6.12,0,11.112,4.919,11.112,11.038c0,6.119-4.994,11.111-11.112,11.111s-11.038-4.994-11.038-11.111
C434.693,207.929,439.613,203.01,445.731,203.01z"/>
<filter id="pictureFilter" >
<feGaussianBlur stdDeviation="15" />
</filter>
</svg>
After doing this, you can use CSS animations on any of the individual SVG elements, just like HTML elements. For example, you could do the following:
svg ellipse { animate: grow 3s infinite; }
Without having the exact SVG code for your arrow, I can't give you more specific direction than that, but can point you in the direction of this article: https://css-tricks.com/using-svg/

Hover button and exchange SVG-filter in <use> with CSS

I have a shadow effect, which I made with a SVG filter to stay flexible for multiple variations of outlines. I apply this filter on <use>-elements and want to exchange this filter when the user hovers the parenting button.
Exchange seems to be important here, because applying a "new" filter on hover works across all major browsers. But changing it from a given filter to another filter seems only to work in Edge?
The CodePen example should bring light into the thing:
http://codepen.io/katerlouis/pen/pRmyoR
All I want is to switch between filters on hover using CSS.
Please no javascript solutions.
Strangely, sometimes clicking the button results in applying the filter which is supposed to come on hover.
I am on a late 2013 MBPr 15'' running El Capitan 10.11.6.
Also tested on other Macs in the Office, same results.
In Edge 14 (Browserstacks Chromeplugin) the buttons work fine.
Firefox (51), Chrome (56) and Safari (9.1.3) fail.
Here is a workaround.
Absolutely position the buttons (i.e one above the other)
Wrap the buttons in a container(<div id="t">)
Use the containers hover .t:hover event to hide the required button.
Example:
body {
padding: 40px;
background: #003A63;
color: white;
}
button {
background: none;
padding: 0;
margin: 0;
border: 0;
outline: 0;
}
.button1 .outline {
fill: white;
filter: url(#button-neutral);
}
.button1 .fill {
fill: #FFED00;
}
.button1:hover .outline {
filter: url(#button-hover);
}
.button2 .outline {
fill: white;
}
.button2 .fill {
fill: #CD1719;
}
.button2:hover .outline {
filter: url(#button-hover);
}
.t:hover .button1 {
z-index: -1;
}
.button1,
.button12 {
position: absolute;
}
Button with filter on both
<div class="t">
<button class="button1">
<svg>
<use class="fill" xlink:href="#button-large-fill" />
<use class="outline" xlink:href="#button-large-outline1" />
</svg>
</button>
<button class="button2">
<svg>
<use class="fill" xlink:href="#button-large-fill" />
<use class="outline" xlink:href="#button-large-outline1" />
</svg>
</button>
</div>
<svg version="1.1" class="hidden-svg">
<defs>
<filter id="button-neutral">
<!-- Um den weißen rahmen des buttons nach oben zu schieben mit dem filter -->
<feOffset in="SourceGraphic" dx="0" dy="-3" result="sourceCopy" />
<feOffset in="SourceAlpha" dx="0" dy="1" result="innenSchatten" />
<feFlood flood-color="gray" flood-opacity="0.8" result="innenSchatten-gefaerbt" />
<feComposite in="innenSchatten-gefaerbt" in2="innenSchatten" operator="in" result="final" />
<feBlend in="final" in2="" mode="multiply" />
<feFlood flood-color="green" result="lol" />
<feComposite in="lol" in2="SourceAlpha" operator="atop" result="lol2" />
<!-- Put everything together. Blur then graphic. -->
<feMerge>
<feMergeNode in="final"/>
<feMergeNode in="sourceCopy" />
</feMerge>
</filter>
<filter id="button-hover">
<!-- Um den weißen rahmen des buttons nach oben zu schieben mit dem filter -->
<feOffset in="SourceGraphic" dx="0" dy="0" result="sourceCopy" />
<feOffset in="SourceAlpha" dx="0" dy="2" result="innenSchatten" />
<feFlood flood-color="gray" flood-opacity="1" result="innenSchatten-gefaerbt" />
<feComposite in="innenSchatten-gefaerbt" in2="innenSchatten" operator="in" result="final" />
<feBlend in="final" in2="" mode="multiply" />
<feFlood flood-color="green" result="lol" />
<feComposite in="lol" in2="SourceAlpha" operator="atop" result="lol2" />
<!-- Put everything together. Blur then graphic. -->
<feMerge>
<feMergeNode in="final"/>
<feMergeNode in="sourceCopy" />
</feMerge>
</filter>
</defs>
<symbol id="button-large-outline1" viewBox="0 0 255 48.9">
<path d="M252.7,15.6c-1.3-3.2-3.3-6.1-5.8-8.4c-2.3-2.2-5.1-3.8-8-4.9c-0.4-0.1-0.7-0.3-1.1-0.4l-1.1-0.3c-0.8-0.2-1.5-0.3-2.3-0.4
c-0.8-0.1-1.6-0.2-2.4-0.2c-0.8,0-1.5,0-2.2,0l-28.3,0.2c-2-0.1-4-0.2-6-0.2c-5.7-0.2-11.4-0.4-17.1-0.5l-8.6-0.2L161.2,0
c-11.4-0.1-22.8,0-34.2,0.2C104.1,0.7,81.3,1.8,58.4,2C47,2.1,35.6,2.1,24.2,2c-0.7,0-1.4,0-2.2,0c-0.8,0-1.5,0-2.3,0.2
c-0.8,0.1-1.5,0.2-2.2,0.4l-1.1,0.3c-0.4,0.1-0.7,0.2-1.1,0.4c-2.9,1-5.5,2.5-7.8,4.6c-2.3,2-4.1,4.6-5.4,7.4c-1.3,2.8-2,5.9-2.1,9
c-0.2,6.2,2.3,12.6,6.9,17c0.3,0.3,0.6,0.5,0.9,0.8c4.2,4.1,9.9,6.7,16.2,6.7h51.1c17.3,0.2,34.6,0.3,51.8,0.2l17.1-0.1
c3.1,0,6.2-0.1,9.3-0.1H232c12.7,0,23-10.3,23-23C255,22.1,254.1,18.7,252.7,15.6z M5,25.6c0-10.5,8.5-19,19-19h208
c5.1,0,9.7,2,13.1,5.3c2.9,3.4,4.5,7.8,4.5,12.2c0,5.1-2.2,10-6,13.4c-1.8,1.7-4,3-6.4,3.9c-0.3,0.1-0.6,0.2-0.9,0.3l-0.9,0.2
c-0.6,0.2-1.2,0.3-1.8,0.3c-0.6,0.1-1.2,0.1-1.9,0.2c-0.3,0-0.6,0-1,0l-1.1,0l-34.2-0.3l-20.9-0.1l-4.8-0.1l-8.6-0.2
c-5.7-0.1-11.4-0.2-17.1-0.2l-17.1-0.1c-22.8-0.1-45.7,0.1-68.5,0.4C47,42,35.6,42.1,24.2,42.3l-1.1,0c-0.4,0-0.6,0-1,0
c-0.6,0-1.2,0-1.9-0.1c-0.6-0.1-1.2-0.1-1.8-0.3l-0.9-0.2c-0.3-0.1-0.6-0.2-0.9-0.3c-2.4-0.8-4.6-2-6.5-3.7
c-1.4-1.2-2.5-2.6-3.5-4.1C5.6,31.1,5,28.5,5,25.6z" />
</symbol>
<symbol id="button-large-fill" viewBox="0 0 255 48.9">
<path class="st0" d="M0.9,23.6c0-11.6,9.4-21,21-21h208c11.6,0,21,9.4,21,21c0,11.6-9.4,21-21,21h-208C10.3,44.6,0.9,35.2,0.9,23.6z
"/>
</symbol>
</svg>
Technically in SVG 1.1, filter is not a CSS property that can be applied to a SVG sub-element so this styling shouldn't work at all - never mind on hover. Various browsers are gradually implementing SVG 2 behavior which expands CSS stylability.
Workaround - apply the style classes to a wrapper div around the SVG, then filters switch just fine on hover. See below:
#shapes {
filter: url(#firstfilter);
}
#shapes:hover {
filter: url(#secondfilter);
}
<div id="shapes">
<svg>
<defs>
<filter id="firstfilter">
<feColorMatrix type="matrix" values=".2 .2 .2 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 0"/>
</filter>
<filter id="secondfilter">
<feGaussianBlur stdDeviation="2"/>
</filter>
</defs>
<path class="st0" d="M0.9,23.6c0-11.6,9.4-21,21-21h208c11.6,0,21,9.4,21,21c0,11.6-9.4,21-21,21h-208C10.3,44.6,0.9,35.2,0.9,23.6z" fill="blue"/>
<path d="M252.7,15.6c-1.3-3.2-3.3-6.1-5.8-8.4c-2.3-2.2-5.1-3.8-8-4.9c-0.4-0.1-0.7-0.3-1.1-0.4l-1.1-0.3c-0.8-0.2-1.5-0.3-2.3-0.4
c-0.8-0.1-1.6-0.2-2.4-0.2c-0.8,0-1.5,0-2.2,0l-28.3,0.2c-2-0.1-4-0.2-6-0.2c-5.7-0.2-11.4-0.4-17.1-0.5l-8.6-0.2L161.2,0
c-11.4-0.1-22.8,0-34.2,0.2C104.1,0.7,81.3,1.8,58.4,2C47,2.1,35.6,2.1,24.2,2c-0.7,0-1.4,0-2.2,0c-0.8,0-1.5,0-2.3,0.2
c-0.8,0.1-1.5,0.2-2.2,0.4l-1.1,0.3c-0.4,0.1-0.7,0.2-1.1,0.4c-2.9,1-5.5,2.5-7.8,4.6c-2.3,2-4.1,4.6-5.4,7.4c-1.3,2.8-2,5.9-2.1,9
c-0.2,6.2,2.3,12.6,6.9,17c0.3,0.3,0.6,0.5,0.9,0.8c4.2,4.1,9.9,6.7,16.2,6.7h51.1c17.3,0.2,34.6,0.3,51.8,0.2l17.1-0.1
c3.1,0,6.2-0.1,9.3-0.1H232c12.7,0,23-10.3,23-23C255,22.1,254.1,18.7,252.7,15.6z M5,25.6c0-10.5,8.5-19,19-19h208
c5.1,0,9.7,2,13.1,5.3c2.9,3.4,4.5,7.8,4.5,12.2c0,5.1-2.2,10-6,13.4c-1.8,1.7-4,3-6.4,3.9c-0.3,0.1-0.6,0.2-0.9,0.3l-0.9,0.2
c-0.6,0.2-1.2,0.3-1.8,0.3c-0.6,0.1-1.2,0.1-1.9,0.2c-0.3,0-0.6,0-1,0l-1.1,0l-34.2-0.3l-20.9-0.1l-4.8-0.1l-8.6-0.2
c-5.7-0.1-11.4-0.2-17.1-0.2l-17.1-0.1c-22.8-0.1-45.7,0.1-68.5,0.4C47,42,35.6,42.1,24.2,42.3l-1.1,0c-0.4,0-0.6,0-1,0
c-0.6,0-1.2,0-1.9-0.1c-0.6-0.1-1.2-0.1-1.8-0.3l-0.9-0.2c-0.3-0.1-0.6-0.2-0.9-0.3c-2.4-0.8-4.6-2-6.5-3.7
c-1.4-1.2-2.5-2.6-3.5-4.1C5.6,31.1,5,28.5,5,25.6z" fill="red" />
</svg>
</div>
Have a look at this workaround on CodePen. It uses opacity with the hover state. I needed to handle transparency in my filters so modified it slightly. I also moved the styling to an external css sheet. I like this better than doing additional div wraps as the hover state can be applied to an polygon rather than a rectangle.
<style>
#group {
cursor: pointer;
}
#group #poly-off {
opacity: 1;
}
#group #poly-on {
opacity: 0;
}
#group:hover #poly-off {
opacity: 0;
}
#group:hover #poly-on {
opacity: 1;
}
</style>
<svg>
<defs>
<filter id="off">
<filter id="on">
<path d="..." id="path"/>
</defs>
<g id="group">
<use id="poly-off" filter="url(#off)" xlink:href="#path"/>
<use id="poly-on" filter="url(#on)" xlink:href="#path"/>
<use fill-opacity="0.5" fill="#ff0000" xlink:href="#path"/>
</g>
</svg>

Resources