Svg Resizes on Hover in Safari Only

In Safari, hovering over SVG elements causes a scrolled element to reset its scroll position?

After spending hours and hours on this, the only way I could figure out how to fix it was to switch from CSS grid to flexbox. ‍♂️

This is the diff that fixed it, if you’re curious.

SVG transition on hover fails in Safari 9.1.2 (11601.7.7)

I was pointed to an article on rrott.com titled "Bug with CSS transition animation for SVG in Safari."

Juicy bits:

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.

and

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.

The article also lists a number of possible solutions:

I see several solutions there but, unfortunately, none of them are
good enough:

  1. add some random data to the link(something like /#timestamp that looks
    ugly but the link will always be ‘unvisited’ for the users).

  2. Do not use animation and inlined SVG in links.

  3. Put link above SVG image using position and z-index so the image is
    'clickjacked’. It works but requires additional js code to handle
    image’s hover event to not loose on hover animation, e.g. add Jquery
    code that will handle clicks on logo and change window.location.

  4. Dynamically move SVG outside of the link in case of Safari.

  5. Leave it as is if you have low amount of Safari users.

I'll go with number 5 for now.

Resizing SVG circle on hover has overflow: hidden issue

Looking better at your code I see that it works in Chrome but can't work in other browsers.
I've made a few changes to your code:

1: I've added a viewBox to your svg, making it a little bigger than the icon, and I've centered it.


  1. you can't modify presentational attributes like cx cy r in css. Presentational attributes belong to svg and can be modified in javascript

3.I've used javascript mouseover / mouseoutevents instead of css hover. If you don't want to use javascript you may try to use css scale for the circle.

let circle= document.querySelector("circle")circle.addEventListener("mouseover",()=>{  circle.setAttributeNS(null,"r", 22)})circle.addEventListener("mouseout",()=>{  circle.setAttributeNS(null,"r", 20)})
circle {fill: #EEE;}
path {fill: #CCC;}
svg{overflow:visible; border:1px solid;}
<svg viewBox="-5 -5 50 50" width="44">     <circle cx="20" cy="20" r=20 />     <path id="test"                 d="M20,31                    C15.4189994,27.2225585 12.5023327,24.2225585 11.25,22                    C10.2743515,20.6156479 10,19.6181623 10,18.1428571                   C10,15.5113854 12.4883456,13 15,13                    C17.3176009,13 18.9621484,13.8491346 20,15.5714286                   C21.0382977,13.8491346 22.6828452,13 25,13                    C27.5116544,13 30,15.5113854 30,18.1428571                    C30,19.6181623 29.7256485,20.6156479 28.75,22                   C27.497816,24.2225585 24.5811493,27.2225585 20,31 Z" />    </svg>

CSS :hover on SVG group area instead of rendered pixels, pointer-events: bounding-box not working cross browser. How to workaround

So pointer-events: bounding-box seems to not be supported by most browsers.

I implemented the workaround @ccprog suggested on the comments section of my question.

I added a <rect fill="none"> element to svg, that is same dimensions than the SVG itself. I added a :hover selector for that element and sibling selector ~ to select its sibling group with the flip class inside.

See CSS:

#mobile-hover {
visibility: visible;
pointer-events: visible;
}
#mobile-hover:hover ~ .group .flip {
-moz-transform-origin:55% 50%;
-webkit-transform-origin: 55% 50%;
transform-origin:55% 50%;
-webkit-animation: flip_left 1.6s forwards;
animation: flip_left 1.6s forwards;
}

I found out I had to add pointer-events: visible to the rect element so it would detect the :hover. I added visibility: visible as a requirement to pointer-events: visible to work.

Below the full new SVG code:

<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="mobile-icon">
<style>
#mobile-hover {
visibility: visible;
pointer-events: visible;
}
#mobile-hover:hover ~ .group .flip {
-moz-transform-origin:55% 50%;
-webkit-transform-origin: 55% 50%;
transform-origin:55% 50%;
-webkit-animation: flip_left 1.6s forwards;
animation: flip_left 1.6s forwards;
}
@keyframes flip_left {
0% {transform: perspective(2000px) rotateY(90deg) skewY(-1deg)}
30% {transform:perspective(2000px) rotateY(-25deg) skewY(-0.8deg)}
50% {transform:perspective(2000px) rotateY(20deg) skewY(0.8deg)}
70% {transform:perspective(2000px) rotateY(-10deg) skewY(-0.8deg)}
100% {transform:perspective(2000px) rotateY(0deg)}
}
</style>
<!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
<title>Mobile solutions</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="mobile" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" >
<rect fill="none" width="40" height="40" id="mobile-hover">
</rect>
<g id="MS_HP_Usecase_Based_Page-Desktop-2A" transform="translate(-766.000000, -418.000000)" stroke="#00A0DF" stroke-width="1.25" class="group">
<g id="Asset-5" transform="translate(766.000000, 418.000000)">
<g class="flip">
<rect id="Rectangle-path" stroke-linecap="round" stroke-linejoin="round" x="12.35" y="7.41" width="15.32" height="25.33" rx="2.03"></rect>
<circle id="Oval" stroke-linecap="round" stroke-linejoin="round" cx="20.01" cy="28.72" r="1.58"></circle>
<path d="M18.43,10.72 L21.48,10.72" id="Shape" stroke-linecap="round" stroke-linejoin="round"></path>
</g>
<circle id="Oval" cx="19.67" cy="19.67" r="19.04"></circle>
</g>
</g>

</g>
</svg>

Works on Chrome, Safari and Firefox and I'm attempting to test IE11 and Edge next.

Many thanks,



Related Topics



Leave a reply



Submit