How to fix jumping / snapping CSS Hover effect in MS Edge - css

I'm experiencing a weird phenomenon using Microsoft Edge (40.15063.674.0) / Microsoft EdgeHTML (15.15063) with the code below. As expected, when you hover over the black box with any browser, it smoothly scales the box to 1.25x its size over 0.5 seconds. The problem happens when a mouse is moving too fast across the box in Edge. What happens is that instead of scaling smoothly, the box jumps/snaps to the desired transformation and then back again. Let’s say a user was moving their mouse fast from one side of the screen to the other and “cutting across the lawn” so to speak across the surface of the box.
In fact, if I move too fast in other browsers, the box doesn't attempt to scale at all. It just stays small unless the mouse movement actually ends up stopping in that area. Even in Internet Explorer this works just fine with as fast as I can move the mouse pointer across it, but only in Edge do I find this behavior. I have to go relatively slow to prevent that jitter-like snap. It doesn't matter what the effect is either. It could be a "scale", a "translateY", etc. If the mouse is moving too fast across the ":hover" it's not smooth in Edge. Is this a known issue? Is there anything I could do to prevent this from happening?
<!DOCTYPE html>
<style>
.box {
background-color: #000;
cursor: pointer;
position: absolute;
left: 200px;
top: 200px;
height: 200px;
width: 200px;
transition: transform 0.5s;
transition-delay: 0.1s; <=== Added this to stop it from jumping
}
.box:hover {
transform: scale(1.25);
}
</style>
<div class="box"></div>
I've even tried replicating the effect using jQuery's ".hover" function to add the CSS attributes when the mouse enters and then take them away when the mouse leaves but to no avail. It behaves exactly the same way. The hover effect jumps/snaps if the mouse is moving too fast in Edge.

This should be a comment, but sub-50 rep here.
You might want to try adding translateZ() or use scale3d() directly, to enable hardware acceleration, and using transition-delay to delay the transition altogether when hovering for less than 100ms.
.box:hover {
transform: scale3d(1.25, 1.25, 1.25);
transition-delay: 0.1s;
}
/* or */
.box:hover {
transform: translateZ(0) scale(1.25);
transition-delay: 0.1s;
}

Related

style calculation for gpu accelerated animation in chrome

This is a chrome only question. I'm using chrome 56 on OSX, but I also tested this on Windows 8 using chrome 57.
I have an animation that is gpu accelerated, using will-change: transform and a keyframe animation using transform: translateY(...) to move an element around the screen.
.block {
height: 20vh;
width: 20vh;
background-color: black;
animation: move 5s linear infinite;
will-change: transform;
}
#keyframes move {
0% { transform: translateY(0%); }
50% { transform: translateY(400%); }
100% { transform: translateY(0%); }
}
Example on codepen: http://codepen.io/nicokoenig/full/PmYaOZ/
The animation itself is handled on the chromes compositor thread and is therefor not affected if the main thread is blocked.
When I record a timeline, I still see that there is a style calculation for each frame.
Why does chrome need to recalculate styles, even if the animation is handled on the compositor thread?
UPDATE
I reviewed my code and added three types of animations.
the first animtion is using a fixed viewport unit (vh) to translate the box.
the second animation is using a fixed pixel value to translate the box.
the third animation is using a percentage value to translate the box.
I also added button to block the main thread - if I hit the button:
the first and second animation will still move around the screen, the third one freezes.
I think that is the answer - an animatoin using translate with percentage values needs to recalculate styles during the whole animation.
The behavior is a known chrome bug.
https://bugs.chromium.org/p/chromium/issues/detail?id=711645
https://bugs.chromium.org/p/chromium/issues/detail?id=389359

CSS transition is sometimes skipped in Chrome

I want to flip an image with a rotation animation when hovering over it (see the code below). When hovering over the image, it rotates around its x-axis for one second (and back when the mouse leaves the image).
The animation works as expected in Firefox and Safari. However, Chrome sometimes skips the animation and flips the image instantly. I don't know how to reliably reproduce the problem because it usually works a few times before the animation is skipped. I have recorded a video, so you can see what I mean: https://www.youtube.com/watch?v=bpgi46F_5RU
Is something wrong with this CSS? I first suspected that it's caused by the rotation angle but the same problem occurs even with other types of animations.
.flippable-container {
float: left;
perspective: 1000px;
}
.flippable {
transition: transform 1s;
}
.flippable-container:hover .flippable {
transform: rotateX(180deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="flippable-container">
<img class="flippable" src="http://lorempixel.com/200/200/food"/>
</div>
Edit: As commented by TylerH, it looks like a bug in Chrome. I see the same problem in this well-known tutorial by David Walsh: http://davidwalsh.name/css-flip. Video: https://www.youtube.com/watch?v=o_TViH4AmZ8. The issue must be related to mouse interaction because the 'Toggle Flip' button below the image works fine.
I have fixed this by putting a z-index and position:relative on all the flippable items. I have no idea why that would affect it but it seems to have done the job.
example: http://jsfiddle.net/L0duLu3c/2/
.flippable-container {
float: left;
perspective: 1000px;
}
.flippable {
transition: 0.6s;
z-index:10;
position:relative;
transform: rotateX(0deg);
}
.flippable-container:hover .flippable {
transform: rotateX(180deg);
z-index:20;
}

Issue with delaying CSS

I am trying to delay a CSS transition, but it seems not to be working. Here is what I want to happen:
Start the video
Move the mouse pointer out of the video
The control bar shrinks, but the play-progress gets larger.
Move mouse pointer back in video, the control bar returns to normal.
As you can see in the CodePen pen, the play-progress bar gets larger before I want it to: http://codepen.io/mboles/pen/mJeJOO
Here is the CSS I am currently using:
#myPlayerID.vjs-has-started.vjs-user-inactive .vjs-progress-control {
-webkit-transform: translateY(-25px);
}
#myPlayerID.vjs-has-started.vjs-user-inactive .vjs-play-progress {
-transition-delay: height 3s;
height: 10px;
}
I have tried to change the order of the transition delay and height, but that did not solve the issue.
Many thanks-
Matt
It turns out with transition-delay you cannot put the property with the delay, it must be explicitly stated using transition-property. So the solution is:
#myPlayerID.vjs-has-started.vjs-user-inactive .vjs-play-progress {
height: 10px;
transition-property: height;
-transition-delay: 3s;
-webkit-transition-delay: 3s;
}

Safari and Touchpad specific issue causing animated element to get stuck

I have a very odd problem that I only observe with Safari, on a touchpad.
When scrolling down, my navbar fades in / down via CSS transition. If I happen to scroll back up, thus removing the class responsible for the transition, the navbar gets stuck visually in the wrong place, only on safari. The CSS / styles say the correct values, and even the hover/click handlers are in the right place.
That is, In the image below, my mouse is hovering at the blank white area, while the navbar stuck below gets highlighted.
There are several odd things about this:
The element is the navbar via global styles, yet only happens on this particular page.
I can't seem to trigger the problem via scrolling with the mouse.
I can only trigger it via very subtle trackpad movements, or fast trackpad movements.
Any suggestions on how to fix this?
Relevant CSS
.is-sticky-slide-down {
#include experimental(animation, fadeInDown .3s ease-out 0s);
}
#-webkit-keyframes fadeInDown {
0% {
opacity: 0;
-webkit-transform: translateY(-20px);
transform: translateY(-20px);
}
100% {
opacity: 1;
-webkit-transform: translateY(0);
transform: translateY(0);
}
}
The problem was due to enabling -webkit-backface-visibility: hidden on elements. Removing this "fix" for hover glitches (like twitching opacity fades) fixed the other glitches on Safari.
To be clear, the fix is to remove -webkit-backface-visibility from affected elements.

Hovering over CSS transition in Safari lightens certain font color

In my CSS I defined a transition for a class. For some reason, when I hover over the class with the transition, the transition-duration for some reason alters the font color elsewhere (form placeholders and certain links). (This happens only in Safari as far as I can tell.)
Here's a jsFiddle that shows what I'm talking about:
http://jsfiddle.net/EJUhd/
Does anyone know why this occurs and how I can prevent it?
I was struggling with a similar issue.
For me, random links throughout the page became apparently bold (clearly something to do with OSX and anti-aliasing in Safari, as Chrome (in windows 7 and OSX) as well as the same version of Safari in Windows worked fine.
The solution is not obvious, and depending on what you are doing might not be optimal, but adding this line of code fixed the issue:
-webkit-transform: translateZ(0);
This basically triggers the GPU to do animation, and the text no longer had artifacts in my site. Do note that it's not always appropriate to use it, as it may use more battery life and use more resources. Sometimes however, it uses less, so basically check the performance when you add it.
You add this to the normal state not the :hover animated state.
img { -webkit-transform: translateZ(0); }
As opposed to on the:
img:hover { /* not here */ }
The other very positive side effect is that depending on the animation you are doing, it might be smoother through the GPU. So you won't get the choppy animation you mention in your follow up post. In my case, the animation was more seamless in safari. I was doing a 120% scale and 5 degree rotation of an image with some box-shadow appearing at the same time. In my situation, it did not reduce CPU usage unfortunately.
There is no more relevant topic I've found for a problem I had, but that's related to mentioned above issue. So, might be helpful for some one.
In two words: I have some container (popup), some element inside.
Appearing goes the following way: container background is fading up to dark via opacity and element inside is scaling up (like coming closer to us from behind). Everything works great everywhere but not in Safari (Mac/Win/iPhone). Safari "initially" shows my container, but it blinks some strange way (tiny short flash appears).
Only adding -webkit-transform: translateZ(0); (to container!!!) did help.
.container {
-webkit-transform: translateZ(0); /* <-- this */
}
.container section {
-webkit-transform: translateZ(0) scale(.92); /* <-- and I added translate here as well */
-webkit-transition: -webkit-transform .4s, opacity .3s;
opacity:0;
}
.container.active section {
-webkit-transform:translateZ(0) scale(1);
-webkit-transition: -webkit-transform .3s, opacity .3s;
opacity:1;
}
But speaking of the transitions, there was also the following part of code:
.container {
...
top:-5000px;
left:-5000px;
-webkit-transition: opacity .5s, top 0s .5s, left 0s 5s, width 0s 5s, height 0s 5s;
}
.container.active {
-webkit-transition: opacity .5s;
top:0;
left:0;
width:100%;
height:100%;
}
considering, that I want to show/hide the popup using only css switching (and also to make it disappear nicely instead just "display:none").
so, somehow on appearing Safari (obviously) was inheriting transition properties besides "opacity" even as I've overloaded them with only -webkit-transition: opacity .5s;
so, adding the following solved the problem:
.container {
...
-webkit-transition: opacity .5s, top 0s 0s, left 0s 0s, width 0s 0s, height 0s 0s;
}
I can't begin to tell you why it's doing this, but Safari isn't changing your text color, it's anti-aliasing the text differently while the transition is in motion. The text edges get smoother, and the text itself becomes thinner. This is extra obvious if you zoom in on the fiddle with accessibility tools. At some smaller sizes, the shading around the button next to the form text shifts too. (Is it possible that Safari is redrawing some things, or reorienting them on a sub-pixel level during the transitions ? Somebody explain this please, it's driving me nuts now!)
Because I have no real idea why it's doing this either, these might not be the best solutions:
Depending on what you're transforming, replacing the css transform with a javascript animation will probably fix it.
For example in your fiddle, the problem also occurred with a scale transformation, but not with a similar jQuery animate function.
There seem to be some shades and styles where the anti-aliasing change is less obvious (at least in the fiddle), so you could also try styling the placeholders and other effected text differently.
(This thread may help with styling the placeholders, if you go that route: Change an HTML5 input's placeholder color with CSS )
Thanks to the identification of anti-aliasing above, as well as help from the articles below, I modified my code to include translate3d(0,0,0) and the problem disappeared:
-webkit-transition-duration: .17s, .17s translate3d(0,0,0);
The transition isn't as smooth as it once was but that's a subject for another question.
Wonky text anti-aliasing when rotating with webkit-transform in Chrome
http://johanbrook.com/design/css/a-fix-for-antialiasing-issues-in-webkit-browsers/
http://www.webkit.org/blog/386/3d-transforms/
i had the same problem, while a transition some text became antialiased. this happen only in anchor text that are positioned relative e with z-index inside an element positioned and with z-index itself.
if i remove all position and index the problem disappear.
There is a similar problem using transition and translate3d. Sometimes any element on the page with :hover styles shows its hover behavior. I have this problem using a slider. Put the -webkit-transform: translateZ(0); to the :hover element and its behavior is normal.
For rotation() maybe it's fine, but for scale() It didn't worked the -webkit-transform: translateZ(0); formula.
I used :
-webkit-font-smoothing: antialiased;

Resources