SVG path element scale transition bug in Firefox browser - css

I am trying to animate a svg path element on hover by adding transform scale transition on it.
It works perfectly as intended on chrome, but on firefox it breaks the transition.
Note: It works without transition animation, but transition is needed in this use case.
HTML:
<svg viewBox="-1.1 -1.1 2.2 2.2">
<g>
<path d="M 1 0 A 1 1 0 0 1 -0.8085734960732691 0.5883951915573843 L 0 0" fill="#ACC6D9" stroke="#ACC6D9" stroke-width="0.01"></path>
<path d="M -0.8085734960732691 0.5883951915573843 A 1 1 0 0 1 -0.8100500340267164 -0.5863607612837983 L 0 0" fill="#93B5D1" stroke="#93B5D1" stroke-width="0"></path>
<path d="M -0.8100500340267164 -0.5863607612837983 A 1 1 0 0 1 0.3063859980740773 -0.9519073590345604 L 0 0" fill="#81A8C9" stroke="#81A8C9" stroke-width="0"></path>
<path d="M 0.3063859980740773 -0.9519073590345604 A 1 1 0 0 1 0.999992891049955 -0.0037706563822101314 L 0 0" fill="#6E9CC1" stroke="#6E9CC1" stroke-width="0"></path>
</g>
<circle cx="0" cy="0" r="0.5" fill="#393D45"></circle>
</svg>
CSS:
path{
transition: transform 0.2s;
}
path:hover{
transform: scale(1.1);
}
JSFiddle link: https://jsfiddle.net/tpkjf15b/2/
Edit:
Chrome 80 (desired output): GIF
Firefox 74 (broken): GIF

This is a weird bug, apparently caused by the fractional stroke-width as demonstrated by this reduced case:
path {
transform: scale(1, 1);
transition: transform 0.2s linear;
}
path:hover {
transform: scale(1.1, 1.1);
}
:checked ~ svg path {
stroke-width: 0.1;
stroke: red;
}
<input id="inp" type="checkbox"><label for="inp">add stroke</label><br>
<svg viewBox="-2.5 -2.5 10 10" width="300">
<path d="M0 0 L2.5 0 L0 2.5 Z" fill="#ACC6D9"></path>
<circle cx="0" cy="0" r="0.5" fill="#393D45"></circle>
</svg>
So for your case, since the strokes are set to the same color as the fills, you may be able to avoid this bug by redefining your shapes in a way you don't need that stroke hack. I guess you used it to avoid antialiasing artifacts, but instead of such an hack, you'd be better using integer coordinates when possible, or maybe simply using a viewBox that would allow stroke-width to be 1 could work.
Also, I didn't checked if this bug has already been referenced, but I can still reproduce on Nightly 76, so you might want to open an issue on Mozilla's bugzilla.

You need to write css transform: translate3d(0px,0px,1px) scale(1); property on path before hover and with hover need to write something like transform: translate3d(0px,0px,1px) scale(1.1);
Finally transform: translateZ(1px); make it run perfectly in FF.
Works too: transform: translate3d(0px,0px,1px);
I hope this will help you lot.
path{
transform: translate3d(0px,0px,1px) scale(1);
transition: transform 0.2s;
}
path:hover{
transform: translate3d(0px,0px,1px) scale(1.1);
}
<svg viewBox="-1.1 -1.1 2.2 2.2" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="backface-visibility: hidden;">
<g>
<path d="M 1 0 A 1 1 0 0 1 -0.8085734960732691 0.5883951915573843 L 0 0" fill="#ACC6D9" stroke="#ACC6D9" stroke-width="0.01"></path>
<path d="M -0.8085734960732691 0.5883951915573843 A 1 1 0 0 1 -0.8100500340267164 -0.5863607612837983 L 0 0" fill="#93B5D1" stroke="#93B5D1" stroke-width="0"></path>
<path d="M -0.8100500340267164 -0.5863607612837983 A 1 1 0 0 1 0.3063859980740773 -0.9519073590345604 L 0 0" fill="#81A8C9" stroke="#81A8C9" stroke-width="0"></path>
<path d="M 0.3063859980740773 -0.9519073590345604 A 1 1 0 0 1 0.999992891049955 -0.0037706563822101314 L 0 0" fill="#6E9CC1" stroke="#6E9CC1" stroke-width="0"></path>
</g>
<circle cx="0" cy="0" r="0.5" fill="#393D45"></circle>
</svg>

Related

CSS animation rotation over 360deg doesn't work in Chrome [duplicate]

This question already has answers here:
Rotating animation doesn't work with chrome
(3 answers)
Closed 10 months ago.
It's been a few hours and I've been trying to make this animation work in Chrome. I've narrowed it down to this: transform: rotate(1080deg); works perfectly in Firefox but not in Chrome (it just doesn't rotate). I found out it rotates in Chrome only if I put less than 360 degrees. But the thing is, I do need to rotate it three times like it does in Firefox.
Here's my code
#path {
animation-name: turn;
transform-origin: 50px 50px;
animation: turn 2s infinite;
}
#keyframes turn {
100% {
transform: rotate(1080deg);
}
}
<svg viewbox="0 0 100 100" id="svg">
<defs>
<linearGradient id="gradient">
<stop offset="26%" stop-color="#632ef4"/>
<stop offset="100%" stop-color="#12ead5"/>
</linearGradient>
</defs>
<path id="path" stroke-linecap="round" stroke-width="15" stroke="url(#gradient)" fill="none" stroke-dasharray="200, 250.2" d="M50 10 a 40 40 0 0 1 0 80 a 40 40 0 0 1 0 -80" transform="scale(1,1) translate(0,0)">
</path>
</svg>
Any ideas? :/
Are you trying to achieve this?
.logo{
animation: rotate 5s linear 0s infinite;
-webkit-animation: rotate 1s linear 0s infinite;
}
#keyframes rotate
{
0% {}
100% {transform: rotate(-360deg);}
}
#-webkit-keyframes rotate
{
0% {}
100% {-webkit-transform: rotate(-360deg);}
}
<svg viewbox="0 0 100 100" id="svg" class="logo">
<defs>
<linearGradient id="gradient">
<stop offset="26%" stop-color="#632ef4"/>
<stop offset="100%" stop-color="#12ead5"/>
</linearGradient>
</defs>
<path id="path" stroke-linecap="round" stroke-width="15" stroke="url(#gradient)" fill="none" stroke-dasharray="200, 250.2" d="M50 10 a 40 40 0 0 1 0 80 a 40 40 0 0 1 0 -80" transform="scale(1,1) translate(0,0)">
</path>
</svg>

svg: styling a path within <use>

I'm trying to use CSS to style the fill of a specific <path> within a <symbol>. I've assigned fill:inherit to the path in the symbol <defs> and I can query the <use> instances of the symbol within the SVG DOM, but I can't seem to access that path within these instances. I looked into inherit for the CSS and currentColor for the fill of the <path> but no luck. Any help is appreciated.
<svg>
<defs>
<style>
symbol#DateCard path.purple {
fill:inherit;
}
use[*|href="#DateCard"] path.purple{
fill:#ff0095;
transition:fill .6s;
}
use[*|href="#DateCard"] path.purple:hover{
path:#ff0000;
}
</style>
<symbol id="DateCard">
<path class="purple" fill="currentColor" d="..."/>
</symbol>
</defs>
<use xlink:href="#DateCard"/>
<svg>
I can query the path within symbol, but when I query the specific paths within a <use> instance, this returns an empty NodeList:
document.querySelectorAll('use[*|href="#DateCard"] path.purple')
Styling inside the shadow DOM needs to be done inside the shadow DOM.
What I learned from Styling SVG Content with CSS | Codrops is that CSS variables are very useful in this case. So, here I created different ways of styling: using a style attribute and style element inside the symbol in combination with CSS variables from the "outside" of the symbol.
.card1 {
--path1-color: #0099CC;
--path2-color: #FFDF34;
}
.card2 {
--path1-color: #00008B;
--path2-color: #FF8C00;
}
.card2:hover {
--path1-color: #00BFFF;
}
<svg viewBox="0 0 200 100" width="400">
<defs>
<symbol id="DateCard">
<style>
.path2 {
fill: var(--path2-color);
transition: fill 1s;
}
.path2:hover {
fill: #800000;
}
</style>
<path class="path1" style="fill: var(--path1-color);transition: fill .6s;" d="M20 40 a 20 20 0 1 1 1 0"/>
<path class="path2" d="M40 60 a 20 20 0 1 1 1 0"/>
</symbol>
</defs>
<use href="#DateCard" class="card1"/>
<use href="#DateCard" class="card2" transform="translate(80 0)"/>
<svg>
Update
OP ask if the hover effect can be achieved using attributes in SVG. An alternative to the :hover pseudo class would be an animation started by the mouse entering and leaving the animated element. Unfortunately it is not as flexible as CSS -- it is difficult to style <animate>.
Here is an example on animating the second <path> in the symbol:
.card1 {
--path1-color: #0099CC;
--path2-color: #FFDF34;
}
.card2 {
--path1-color: #00008B;
--path2-color: #FF8C00;
}
.card2:hover {
--path1-color: #00BFFF;
}
<svg viewBox="0 0 200 100" width="400">
<defs>
<symbol id="DateCard">
<style>
.path2 {
fill: var(--path2-color);
}
</style>
<path class="path1" style="fill: var(--path1-color);transition: fill .6s;" d="M20 40 a 20 20 0 1 1 1 0"/>
<path class="path2" d="M40 60 a 20 20 0 1 1 1 0">
<animate attributeName="fill" dur="1s" values="#FF8C00;#800000" begin="mouseenter" fill="freeze" />
<animate attributeName="fill" dur="1s" from="#800000" to="#FF8C00" begin="mouseleave" fill="freeze" />
</path>
</symbol>
</defs>
<use href="#DateCard" class="card1"/>
<use href="#DateCard" class="card2" transform="translate(80 0)"/>
<svg>

SVG only (no JS) - line/path animation

I can't think my way through this one... I can't really add mark-up in a project, only CSS (for many boring reasons with who I'm collaborating remotely with).
The end client wants a loading animation of their logo path being drawn but not linear, more ease-in-out (slow-fast-slow) sort of thing. To illustrate what I mean, see jsfiddle I've done: https://jsfiddle.net/tobzzzz/djf7oth2/ (their logo is a bit like a speech mark, I've done a circle for ease for the demo).
The logo will sit on top of an image background, not a white/solid colour background, so my fiddle solution won't work of two circles layered. I added light grey background to demonstrate how it doesn't work.
The IDEAL solution would be SVG only (using SVG animation not CSS animation), I'd then convert it into data and put it as a background-image.
If it can't be done with SVG animation only, I'd like to know if it can be done with SVG and CSS combo. But it absolutely 100% cannot be JS.
Any good ideas?
body {
background: #eee
}
.black {
stroke-dasharray: 350;
stroke-dashoffset: 350;
animation: dash 4s linear infinite;
}
.white {
stroke-dasharray: 350;
stroke-dashoffset: 350;
animation: dash2 4s ease-in-out infinite;
}
#keyframes dash {
80% {
stroke-dashoffset: 0;
}
}
#keyframes dash2 {
100% {
stroke-dashoffset: 0;
}
}
<svg class="path" width="84" height="84" xmlns="http://www.w3.org/2000/svg">
<path class="black" fill="none" stroke="#000000" stroke-width="4" d="M 80.889194,41.80541 C 80.889194,63.45198 63.341174,81 41.694594,81 20.048024,81 2.5,63.45198 2.5,41.80541 2.5,20.158827 20.048024,2.61081 41.694594,2.61081 c 21.64658,0 39.1946,17.548017 39.1946,39.1946 z"/>
<path class="white" fill="none" stroke="white" stroke-width="5" d="M 80.889194,41.80541 C 80.889194,63.45198 63.341174,81 41.694594,81 20.048024,81 2.5,63.45198 2.5,41.80541 2.5,20.158827 20.048024,2.61081 41.694594,2.61081 c 21.64658,0 39.1946,17.548017 39.1946,39.1946 z"/>
</svg>
You need to animate the stroke-dasharray, not only the stroke-dashoffset. You can add multiple numbers to the value of the dasharray, defining alternating lengths of dashes and gaps. So, if you circle with r="40" has a circumference of 251,4,
0 251.4 is a stroke of 0 length and a gap around the whole circumference
125.7 125.7 is a half-circle stroke and a half-circle gap
and then reduce the stroke length again
At the same time, move the start of the stroke around the circle by animating the offset.
There is a lot of finetuning you can do with other intermediate values, by distributing the keyTimes differently and with easing functions. Here is a basic variant with linear animations:
<svg width="84" height="84">
<circle r="40" cx="42" cy="42" style="fill: none;stroke: black;stroke-width: 4;">
<animate attributeName="stroke-dasharray" dur="3s" repeatCount="indefinite"
keyTimes="0;0.5;1" values="0 251.4;125.7 125.7;0 251.4" />
<animate attributeName="stroke-dashoffset" dur="3s" repeatCount="indefinite"
keyTimes="0;0.5;1" values="0;-100;-251.4" />
</circle>
</svg>
Inkscape makes it easy to modify a path and to save it.
Below the svg includes from and to paths.
The tag animate after a 1 second delay makes the eye blinks twice and then stops:
<svg style="vertical-align:middle;opacity:0.7"
width="13" height="13"
viewBox="0 0 12 12"
xmlns="http://www.w3.org/2000/svg">
<path id="glass_1" d="m6 3c2.58 0 4.23 2.07 4.84 3-.62.93-2.26 3-4.84 3s-4.23-2.07-4.84-3c.62-.93 2.26-3 4.84-3m0-1c-4 0-6 4-6 4s2 4 6 4 6-4 6-4-2-4-6-4zm0 2a2 2 0 1 0 2 2 2 2 0 0 0 -2-2z"
fill="green">
</path>
<animate xlink:href="#glass_1" attributeName="d" attributeType="XML"
from="m6 3c2.58 0 4.23 2.07 4.84 3-.62.93-2.26 3-4.84 3s-4.23-2.07-4.84-3c.62-.93 2.26-3 4.84-3m0-1c-4 0-6 4-6 4s2 4 6 4 6-4 6-4-2-4-6-4zm0 2a2 2 0 1 0 2 2 2 2 0 0 0 -2-2z"
to="m6.1 5.9c2.6 0 3-0.019 4.7 0.092-1.4 0.58-2.2 0.59-4.7 0.59s-3.8 0.0053-4.9-0.59c1.2-0.069 2.4-0.092 5-0.092m0-1c-4 0-6.1 1.1-6.1 1.1s2.1 1.6 6.1 1.6c4 0 5.9-1.6 5.9-1.6s-1.9-1.1-5.9-1.1zm-0.13-0.91c-1.8 0-2.7 2.2-1.4 3.4s3.4 0.37 3.4-1.4c0-1.1-0.9-2-2-2z"
begin="1s;op.end"
repeatCount="2"
dur="0.5s">
</animate>
</svg>
have you looked at this?
https://maxwellito.github.io/vivus-instant/
You can drag in any SVG and it has limited animation capabilities automatically.

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 mix-blend-mode not showing in firefox

Testing an svg using mix-blend-mode: multiply in Firefox 44 and it will not apply the blend-mode at all. But on another page I have a similar SVG and it shows fine. So it seems like the problem is with the SVG code itself...
I've seen a few other people having similar issues and have looked at all the proposed solutions, none of which worked for me. (adding background-color to div, adding a transparent border)
HTML:
<div class="about-background clearfix">
<object class="willItBlend" data="../svg/about-bg.svg" type="image/svg+xml"></object>
<img class="blender" src="../svg/about-bg.png" />
</div>
CSS (png fallback):
#supports not(mix-blend-mode: multiply) {
.blender {
display: block;
}
.willItBlend {
display: none;
}
SVG:
<svg width="489" height="441" viewBox="0 0 489 441" xmlns="http://www.w3.org/2000/svg">
<title>
about-bg
</title>
<style>
path { mix-blend-mode: multiply; }
ellipse { mix-blend-mode: multiply; }
</style>
<g fill="none" fill-rule="evenodd">
<g transform="translate(-236.973 -308)" stroke-width="33.6">
<ellipse stroke="#E2E42E" cx="345.986" cy="357.28" rx="345.986" ry="357.28"/>
<ellipse stroke="#ED1F71" cx="346.972" cy="358.298" rx="295.715" ry="305.368"/>
<ellipse stroke="#03A8DE" cx="346.972" cy="358.298" rx="244.458" ry="252.437"/>
</g>
<g transform="translate(-284 -294.56)">
<path d="M345.986 714.56c191.083 0 345.987-159.96 345.987-357.28C691.973 159.96 537.07 0 345.986 0 154.903 0 0 159.96 0 357.28 0 554.6 154.903 714.56 345.986 714.56z" stroke="#E2E42E" stroke-width="11.2"/>
<ellipse stroke="#ED1F71" stroke-width="22.4" cx="346.972" cy="358.298" rx="295.715" ry="305.368"/>
<ellipse stroke="#03A8DE" stroke-width="22.4" cx="346.972" cy="358.298" rx="244.458" ry="252.437"/>
</g>
<g transform="translate(-138.44 -164.64)">
<path d="M247.453 510.72c136.665 0 247.453-114.33 247.453-255.36C494.906 114.33 384.118 0 247.453 0 110.788 0 0 114.33 0 255.36c0 141.03 110.788 255.36 247.453 255.36z" stroke="#E2E42E" stroke-width="11.2"/>
<ellipse stroke="#ED1F71" stroke-width="5.6" cx="248.573" cy="256.48" rx="211.623" ry="218.4"/>
<ellipse stroke="#03A8DE" stroke-width="5.6" cx="247.453" cy="256.48" rx="174.673" ry="180.32"/>
</g>
</g>
</svg>

Resources