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:
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 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.Dynamically move SVG outside of the link in case of Safari.
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.
- 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 / mouseout
events 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
Change Image Onclick for a Set Amount of Time
Creating a Custom Attribute with Angularjs
Hover Effects on Irregular Polygons in CSS
Isotope Jquery Plugin Doesn't Show Properly on Chrome
Pause/Resume CSS Animations When Switching Tabs
Animating Max-Height with Pure Js
How to Over-Ride CSS with User-CSS on Mobile Safari
Bootstrap 4 Input Field in Popover
Change Image on Radio Button Click Using Js or HTML
Disable (Exclude) Bootstrap for One Div on a Page
Css: Set Divs Horizontally in 2 Rows
Using Modernizr and Jquery to Animate If CSS3 Transitions Don't Exist