Reputation: 3950
I'm building an AngularJS application that shows and hides an element by transitioning its opacity. The element is also being rotated by applying a CSS keyframe animation. The problem I'm having is the transition or animation stutters.
When the element has an opacity of 1 and the transition fades it out to 0 then the element appears to go back a few frames. This is better demonstrated in a GIF. You can see it jump back just before the opacity changes.
This is my CSS.
.square {
width: 100px;
height: 100px;
margin: 50px;
background: black;
}
.appear.ng-hide-add {
-webkit-transition: opacity 300ms linear;
opacity: 1;
}
.appear.ng-hide-add.ng-hide-add-active {
opacity: 0;
}
.appear.ng-hide-remove {
-webkit-transition: opacity 300ms linear;
opacity: 0;
}
.appear.ng-hide-remove.ng-hide-remove-active {
opacity: 1;
}
@-webkit-keyframes rotate {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
}
}
.rotate {
-webkit-animation: rotate 1.5s infinite linear;
}
This is my HTML.
<div ng-app="app" ng-init="show = true">
<p>Toggle the opacity of the square. Sometimes the rotation is interrupted when the opacity transitions from 1 to 0.</p>
<button ng-click="show =!show">Toggle</button>
<div class="square appear rotate" ng-show="show"></div>
</div>
You can play with the whole thing in this codepen. Hoping someone can point me in the right direction.
Upvotes: 6
Views: 7148
Reputation: 16274
Here's one more workaround just for the fun of it. Slightly less ugly than the first one I suggested. Change the box background color opacity: http://codepen.io/anon/pen/DpuEh
HTML:
<div ng-app="app" ng-init="show = true">
<button ng-click="show = !show">Toggle</button>
<div class="square appear rotate" ng-class="{'hidden': !show}"></div>
</div>
CSS:
.square {
width: 100px;
height: 100px;
margin: 50px;
-webkit-transition: background 300ms linear;
background: black;
}
.square.hidden {
background: rgba(0, 0, 0, 0);
}
I'm using rgba
to set the background opacity. Just setting the background to white
would also have worked in this simple case.
Upvotes: 2
Reputation: 16274
Ugly workaround that may or may not be suitable, depending on your situation: instead of hiding the element (shows the bug) or a container (also shows the bug), you can fade in a background-colored element on top of it.
HTML:
<div ng-app="app" ng-init="show = false">
<button ng-click="show =!show">Toggle</button>
<div class="appear" ng-show="show"></div>
<div class="square rotate"></div>
</div>
CSS:
.appear {
background: white;
width: 200px;
height: 200px;
position: absolute;
top: 30px;
left: 0;
z-index: 2;
}
Obviously you might need more sophisticated CSS for a more sophisticated layout, but hopefully you get the idea.
CodePen: http://codepen.io/anon/pen/IwBHj
Upvotes: 1
Reputation: 60507
This is evidently a WebKit bug. This is clearly not how the CSS should behave, and it does behave as expected in Firefox if you remove the vendor prefixes. You will notice that the animation resets when an additional animations/transitions are applied. This is similar to a known bug that was recently fixed in which multiple CSS transitions being applied at different times would cause a layout flash. I would recommend reporting the bug to the WebKit team so that it can be fixed.
Upvotes: 1
Reputation: 2078
I would consider using translate3D on the transform to force hardware acceleration.
-webkit-transform: translate3d(0,0,0);
This uses hardware acceleration (GPU) for the CSS transitions.
Upvotes: 0