Bug with CSS transition animation for SVG in Safari.
Recently I’ve been working on an interesting issue in GitLab Community Edition and decided to share results of my research with the community.
The issue
Assume we have SVG image inlined into a page where the following SCSS animates .tanuki-shape
SVG on hover:
1
2
3
4
5
6
7
8
.tanuki-shape {
transition: all 0.8s;
&:hover, &.highlight {
fill: rgb(255, 255, 255);
transition: all 0.1s;
}
}
In Chrome and Firefox, the logo animation has a nice fade-out effect on each piece:
But Safari doesn’t seem to respect the transition property, and we get no fade:
Note, there are several ways to put SVG image into a page:
1 use it directly in an
<img>
tag.2 use SVG as
background-image
of a div.3 using inline SVG.
The only way to have CSS animation in SVG is inlining images into a page and I am describing this particular case.
Investigation
Assumption:
The very first assumption was: the reason why this transition animation does not work in Safari is because it is inside a link. It looked like Safari stops all animation on the image once the link’s hover
event is triggered, but I found nothing about this in specs and standards.
Research:
Above assumption was a quite correct, as sometimes this transition animation was working correctly on one machine while failing unpredictable on another and vice versa. It looked strange and I saw no consistent pattern there.
I did a research and after deeper investigation and dozens manual tests, I found that the transition stops working for all the visited links and that could be the reason why I was not able to reproduce the issue on one machine while it is failed on another. Here is my Proof of Concept:
Looks like Safari has the same protection of users’ history as Mozilla, but with its own realisation: Privacy and the :visited selector
Sadly, changing :visited
pseudo in CSS as well as using xmlns:xlink
inside of SVG does not make transition working again and there are no hacks there.
Solution:
I see several solutions there but, unfortunately, none of them are good enough:
add some random data to the link(something like
/#timestamp
that looks ugly but the link will always be ‘unvisited’ for the users).Do not use animation and inlined SVG in links.
Put link above SVG image using
position
andz-index
so the image is ‘clickjacked’. It works but requires additional js code to handle image’shover
event to not looseon hover
animation, e.g. add Jquery code that will handle clicks on logo and changewindow.location
.Dynamically move SVG outside of the link in case of Safari.
Leave it as is if you have low amount of Safari users.
Here is my Merge Request to the project: Fixes for issue with poor logo transition animation on safari
This solution moves logo outside of the link and sets logo above it using position and z-index so the link is ‘clickjacked’: When you hover the image, the animation is working as expected, but to handle clicks I had to add jquery call.
1
2
3
4
5
6
7
8
9
10
.home {
z-index: 1;
position: absolute;
}
#logo {
z-index: 2;
position: absolute;
cursor: pointer;
}
Where #logo
is a new div that has our .tanuki-shape
SVG image inside.
SVG image in Safari before | and after the change |
---|---|
![]() |
![]() |