Distorted CSS drop-shadow on SVG after applying CSS transform in Chrome - css

The title sums it up. Using the code below you will see the drop-shadow looks fine in Firefox-- whether or not the transform is applied-- but the drop-shadow becomes distorted in Chrome when the transform is applied.
g {fill: red}
svg {-webkit-filter: drop-shadow(0 0 10px blue); filter: drop-shadow(0 0 10px blue);}
/* The style below will distort the drop-shadow in Chrome, but not Firefox */
svg {-webkit-transform: scaleX(-1); transform: scaleX(-1);}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns-xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 87.4 31.1" xml-space="preserve" >
<g>
<path d="M2,28.2l-0.5-0.5C10,19,14.8,9.5,14.9,9.4l0.6,0.3C15.4,9.8,10.6,19.4,2,28.2z"/>
<path d="M15.1,9.9c-0.2,0-4.1-1.1-5.2-7.3l0.6-0.1c1,5.8,4.7,6.8,4.7,6.8L15.1,9.9z"/>
<path d="M14.9,9.8c-0.1-0.2-3.3-4.6-2.1-7.9l0.6,0.2c-1.1,2.9,2,7.2,2,7.3L14.9,9.8z"/>
<path d="M14.9,9.7c0-0.2-1.2-4.4,1.9-9.4l0.6,0.3c-2.9,4.8-1.8,8.8-1.8,8.9L14.9,9.7z"/>
<path d="M15.4,9.9c-0.2,0-0.3,0-0.3,0l0-0.6c0,0,3.3,0.2,9-2.6l0.3,0.6C19.5,9.7,16.4,9.9,15.4,9.9z"/>
<path d="M15.5,9.7l-0.6-0.2c0-0.1,0.4-1,3.2-3.9L18.5,6C15.9,8.8,15.5,9.6,15.5,9.7z"/>
<path d="M21.4,12.5c-5,0-6.4-2.7-6.5-2.8l0.6-0.3l-0.3,0.1l0.3-0.1c0.1,0.1,1.5,2.8,7.1,2.4l0,0.6C22.2,12.5,21.8,12.5,21.4,12.5z"/>
<path d="M20,10.1c-2.7,0-4.8-0.3-4.9-0.3l0.1-0.6c0.1,0,5.6,0.7,10.4-0.2l0.1,0.6C23.8,10,21.8,10.1,20,10.1z"/>
<path d="M0.6,29.9C0.2,29.8,0,29.6,0,29.6c-0.2-0.8,0.5-1.3,1.5-2.4c0.7-0.8,2-1.3,3.6-3.3c0.7-0.4,1.3-0.6,0.4,0.4
c-2.5,2.7-2,2.9-3,4C1.8,29.1,1.1,29.9,0.6,29.9z"/>
</g>
</svg>
Is there a way to avoid the drop-shadow distortion in Chrome?

One alternative solution would be to use transform: rotateY(180deg); instead of scale.
g {fill: red}
svg {-webkit-filter: drop-shadow(0 0 10px blue); filter: drop-shadow(0 0 10px blue);}
/* The style below will distort the drop-shadow in Chrome, but not Firefox */
svg {transform: rotateY(180deg);}
<svg viewBox="0 0 87.4 31.1" >
<g>
<path d="M2,28.2l-0.5-0.5C10,19,14.8,9.5,14.9,9.4l0.6,0.3C15.4,9.8,10.6,19.4,2,28.2z"/>
<path d="M15.1,9.9c-0.2,0-4.1-1.1-5.2-7.3l0.6-0.1c1,5.8,4.7,6.8,4.7,6.8L15.1,9.9z"/>
<path d="M14.9,9.8c-0.1-0.2-3.3-4.6-2.1-7.9l0.6,0.2c-1.1,2.9,2,7.2,2,7.3L14.9,9.8z"/>
<path d="M14.9,9.7c0-0.2-1.2-4.4,1.9-9.4l0.6,0.3c-2.9,4.8-1.8,8.8-1.8,8.9L14.9,9.7z"/>
<path d="M15.4,9.9c-0.2,0-0.3,0-0.3,0l0-0.6c0,0,3.3,0.2,9-2.6l0.3,0.6C19.5,9.7,16.4,9.9,15.4,9.9z"/>
<path d="M15.5,9.7l-0.6-0.2c0-0.1,0.4-1,3.2-3.9L18.5,6C15.9,8.8,15.5,9.6,15.5,9.7z"/>
<path d="M21.4,12.5c-5,0-6.4-2.7-6.5-2.8l0.6-0.3l-0.3,0.1l0.3-0.1c0.1,0.1,1.5,2.8,7.1,2.4l0,0.6C22.2,12.5,21.8,12.5,21.4,12.5z"/>
<path d="M20,10.1c-2.7,0-4.8-0.3-4.9-0.3l0.1-0.6c0.1,0,5.6,0.7,10.4-0.2l0.1,0.6C23.8,10,21.8,10.1,20,10.1z"/>
<path d="M0.6,29.9C0.2,29.8,0,29.6,0,29.6c-0.2-0.8,0.5-1.3,1.5-2.4c0.7-0.8,2-1.3,3.6-3.3c0.7-0.4,1.3-0.6,0.4,0.4
c-2.5,2.7-2,2.9-3,4C1.8,29.1,1.1,29.9,0.6,29.9z"/>
</g>
</svg>

Related

SVG line cross animation for icons

I have two icons, one in original state, one in crossed off state.
I want to animate the cross line but changing dash-offset is not useful since those are two different svgs.
I'm looking at these animated icons but still couldn't figure out the magic part. I want to ask:
what should be the transition work flow?
I prefer to use pure CSS, is it possible?
A working example would be appreciated.
The animated icons on that page are quite complicated (more that they need to be IMO). But basically what they are doing is sliding a rectangular mask in from right to left, that covers the first icon, and uncovers the second icon.
Here is a simplified version, using pure CSS, that hopefully makes it clearer.
svg {
width: 100px;
height: 100px;
}
/* slides the two masks to the left on hover */
svg:hover #bottom-rect,
svg:hover #top-rect
{
transition: transform 500ms;
transform: translate(-24px, 0px);
}
/* slides the two masks back to the right when not hovered */
svg #bottom-rect,
svg #top-rect {
transition: transform 500ms;
transform: translate(0px, 0px);
}
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<defs>
<mask id="bottom">
<rect id="bottom-rect" width="24" height="24" fill="white" stroke="none"/>
</mask>
<mask id="top">
<rect id="top-rect" x="24" width="24" height="24" fill="white" stroke="none"/>
</mask>
</defs>
<g mask="url(#bottom)">
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
<path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
<line x1="12" y1="19" x2="12" y2="23"></line>
<line x1="8" y1="23" x2="16" y2="23"></line>
</g>
<g mask="url(#top)">
<line x1="1" y1="1" x2="23" y2="23"></line>
<path d="M9 9v3a3 3 0 0 0 5.12 2.12M15 9.34V4a3 3 0 0 0-5.94-.6"></path>
<path d="M17 16.95A7 7 0 0 1 5 12v-2m14 0v2a7 7 0 0 1-.11 1.23"></path>
<line x1="12" y1="19" x2="12" y2="23"></line>
<line x1="8" y1="23" x2="16" y2="23"></line>
</g>
</svg>
An approach with CSS.
You just show/hide the icons you want on hover. To animate the line, use CSS animations with stroke-dasharray and stroke-dashoffset. Comments in code.
/* for demo */
svg {
width: 100px;
height: 100px;
border: 1px solid black;
}
/* hide the off icon */
svg .off {
opacity: 0;
}
/* when user hovers SVG, the on icon is hidden... */
svg:hover .on {
opacity: 0;
}
/* ... and the off icon is shown */
svg:hover .off {
opacity: 1;
}
/* initial values for the stroke
-- these can be obtained with JS,
-- or you can work them out manually for CSS
*/
svg .line {
stroke-dashoffset: 40px;
stroke-dasharray: 40px;
}
/* when user hovers SVG, animate the line */
svg:hover .line {
animation: addLine 800ms forwards;
}
/* values for line animation */
#keyframes addLine {
from {
stroke-dashoffset: 40px;
}
to {
stroke-dashoffset: 0;
}
}
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<g class="on">
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
<path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
<line x1="12" y1="19" x2="12" y2="23"></line>
<line x1="8" y1="23" x2="16" y2="23"></line>
</g>
<g class="off">
<line class="line" x1="1" y1="1" x2="23" y2="23"></line>
<path d="M9 9v3a3 3 0 0 0 5.12 2.12M15 9.34V4a3 3 0 0 0-5.94-.6"></path>
<path d="M17 16.95A7 7 0 0 1 5 12v-2m14 0v2a7 7 0 0 1-.11 1.23"></path>
<line x1="12" y1="19" x2="12" y2="23"></line>
<line x1="8" y1="23" x2="16" y2="23"></line>
</g>
</svg>

SVG animation on hover starts from wrong position in firefox

When you hover on element in Chrome, the bottom part of the clock starts moving down. If you try to do this in firefox, it starts from wrong position.
HTML
<g id="clock_bottom_3" opacity="0.316786674" transform="translate(72.000000, 306.000000)">
<ellipse id="Oval" fill="url(#radialGradient-1)" opacity="0.24" transform="translate(87.000000, 52.000000) rotate(-180.000000) translate(-87.000000, -52.000000) " cx="87" cy="52" rx="87" ry="52"></ellipse>
<ellipse id="Oval" fill="url(#radialGradient-2)" opacity="0.24" transform="translate(117.000000, 52.000000) scale(-1, 1) rotate(-180.000000) translate(-117.000000, -52.000000) " cx="117" cy="52" rx="87" ry="52"></ellipse>
</g>
CSS:
#clock_bottom_3 {transition: transform 0.3s;}
svg:hover #clock_bottom_3 {transform: translate(72px, 320px);}
https://jsfiddle.net/kd7x068g/
It seems you might have struck a bug in Firefox.
Here's a simplified version of your SVG:
#clock_bottom_3 {transition: transform 0.3s;}
svg:hover #clock_bottom_3 {transform: translate(72px, 320px);}
<svg width="588px" height="512px" viewBox="0 0 588 512">
<g id="clock_bottom_3" transform="translate(72 306)">
<ellipse fill="blue" cx="87" cy="52" rx="87" ry="52"></ellipse>
</g>
</svg>
You are transitioning between two translate() transforms on hover. This works in Chrome, but doesn't work in Firefox. It appears as if Firefox is ignoring the initial transform on the object and transitioning from (0,0) instead.
The fix for now is to wrap "clock_bottom_3" in another group and apply the transition to that instead.
#clock_bottom_3_wrap {transition: transform 0.3s;}
svg:hover #clock_bottom_3_wrap {transform: translate(0px, 14px);}
<svg width="588px" height="512px" viewBox="0 0 588 512">
<g id="clock_bottom_3_wrap">
<g id="clock_bottom_3" transform="translate(72 306)">
<ellipse fill="blue" cx="87" cy="52" rx="87" ry="52"></ellipse>
</g>
</g>
</svg>
If we make that modification to your original fiddle, it works.

image inside svg not scaling on mouse hover

I have a image inside my svg, and i want to scale that image on mouse hover using css.
this is my svg document.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1260 720" width="1260px" height="740px" preserveAspectRatio="xMinYMin meet">
<g>
<g id="step-5">
<image overflow="visible" class="step-circle-5" width="173" height="173"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAK0AAACsCAYAAAAJ8yzmAAA
ACXBIWXMAAAkSAAAJEgFGxru7AAAA.. transform="matrix(0.9334 0 0 0.9389 843.2724 402.5272)"></image>
<text transform="matrix(1.0004 0 0 1 825.4094 649.0767)" fill="#A9D48D" font-size="92">5</text>
</g>
....
</g>
</svg>
And here is the css
.step-circle-5:hover{
transform: translate(843.2724 402.5272) scale(1.2) translate(843.2724 402.5272);
-webkit-transform: translate(843.2724 402.5272) scale(1.2) translate(843.2724 402.5272);
}
Here is the complete code on codepen
I think that your selector is wrong, try this:
/* .step-circle-1 is last <image> tag in svg document */
svg .step-circle-1:hover{
cursor:pointer;
transform: scale(1.2)
translate(5%,50%);
}
With the translate you must play a little bit...

svg css animation without stroke

I am trying to make a hamburger menu with svg, but my problem is that my svg is only a fill, without stroke.
How can I change the size of each line on hover ?
Here is the svg:
<svg id="menu" x="0px" y="0px" width="64.948px" height="30.172px" viewBox="0 0 64.948 30.172" style="enable-background:new 0 0 64.948 30.172;" xml:space="preserve">
<style type="text/css">
.st1{
fill:#CE0011;
transition:all .8s ease;
}
</style>
<path class="st1" id="line1" d="M64.948,2.73c-1.098,3.107-2.33,4.997-6.812,4.952c-16.91-0.17-33.824-0.068-50.942-0.068 c0.401-3.24,1.888-4.961,6.324-4.931C30.436,2.8,47.357,2.73,64.948,2.73z"/>
<path class="st1" id="line2" d="M60.676,12.856c-0.947,2.002-1.688,3.567-2.365,4.999c-18.135,0-36.122,0-54.159,0 c0.843-4.768,1.126-4.995,6.183-4.997c15.25-0.006,30.499-0.002,45.749-0.002C57.404,12.856,58.723,12.856,60.676,12.856z"/>
<path class="st1" id="line3" d="M56.599,23.023c-0.459,4.176-2.703,5.04-6.567,4.994C33.458,27.817,16.88,27.932,0,27.932 c0.348-2.549,0.455-4.888,3.908-4.894C21.379,23.006,38.849,23.023,56.599,23.023z"/>
</svg>
As aspsmn said, try ...
svg:hover .st1 {
transform: scale(0.8);
}
I built a fiddle (http://jsfiddle.net/rfornal/pv0np9pw/) to test this and actually tried with a scale up to 1.2 ... this became an issue since I hadn't changed the size of the viewbox.
However, this did prove the working concept.

rotating an object with transform-origin not working in firefox [duplicate]

This question already has an answer here:
Transform origin on SVGs in Firefox
1 answer
I have an SVG:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="42px"
height="51px" viewBox="0 0 426 513" xml:space="preserve" id="aniBin">
<g id="Bin">
<g id="cap">
<path style="fill:#7B7A7A;" d="M414,71H301.916c0.05-0.411,0.084-0.826,0.084-1.25v-55.5c0-0.543-0.055-1.072-0.136-1.592
c0.081-0.537,0.136-1.083,0.136-1.642v-0.032C302,4.918,297.082,0,291.016,0H135.984C129.918,0,125,4.918,125,10.984v0.032
c0,0.56,0.055,1.105,0.136,1.642c-0.081,0.52-0.136,1.049-0.136,1.592v55.5c0,0.424,0.034,0.839,0.084,1.25H12
C5.373,71,0,76.373,0,83v25c0,6.627,5.373,12,12,12h402c6.627,0,12-5.373,12-12V83C426,76.373,420.627,71,414,71z M146,69.75V22
h135v47.75c0,0.424,0.034,0.839,0.084,1.25H145.916C145.966,70.589,146,70.174,146,69.75z"/>
</g>
<g id="bin">
<rect x="33" y="133" style="fill:#3975B1;" width="362" height="12"/>
<path style="fill:#3975B1;" d="M383.5,133h-338c-12,0-12.5-0.5-12.5,11.5v356c0,6.627,5.873,12.5,12.5,12.5h338
c6.627,0,11.5-5.873,11.5-12.5v-356C395,132.5,396.75,133,383.5,133z M91,469H75V179h16V469z M157,469h-16V179h16V469z M221,469
h-16V179h16V469z M285,469h-16V179h16V469z M348,469h-16V179h16V469z"/>
</g>
</g>
</svg>
And Css I am Applying is:
#aniBin {
overflow: visible;
}
#Bin:hover #cap {
transition-duration: 400ms;
transform: rotate(-150deg);
transform-origin:0% 100%;
}
This Animation is working on Chrome but seems transform-origin is not applied in Firefox I have read this but unable to fix this.
You have to add
-moz-
like this:
-moz-transform-origin: some value;
, because of the browser support of Mozilla.
Also you should use
-webkit-
for Safari and Chrome.

Resources