Choppy CSS3 animation on iPhone 4 - animation

I have a pretty simple (or at least I think it is) animation. All I'm animating is the -webkit-background-size.
#bubble { position:relative; width:397px; height:326px; background:url('../img/mobile/webkit/bubble.png') no-repeat bottom right; -webkit-background-size:100% 100%; -webkit-animation-name:resize; -webkit-animation-duration:1s; -webkit-animation-iteration-count:1; -webkit-animation-timing-function: ease-in; }
#-webkit-keyframes resize {
0% { -webkit-background-size:0% 0%; }
90% { -webkit-background-size:100% 100%; }
95% { -webkit-background-size:95% 95%; }
100% { -webkit-background-size:100% 100%; }
}
It works nicely in Safari on the desktop, but on the iPhone, the animation is very choppy. Which is odd, because I've seen lots of demonstrations of CSS animation on my iPhone that run silky smooth. Am I going about this animation the wrong way?
Basically, it's a speech bubble that starts out at 0%, scales up to 100%, then 95%, then 100%. Sort of like a bounce-out ease effect.

You must do some trickery to allow the GPU to kick in, if you can scale the whole div instead of just the background then this will make it smooth...
#bubble {
position:relative;
width:397px;
height:326px;
background:url('../img/mobile/webkit/bubble.png') no-repeat bottom right;
-webkit-background-size:100% 100%;
-webkit-animation: resize 1s ease-in 1; /*shorthands are better!*/
-webkit-transform: scale3d(100%, 100%, 1);
}
#-webkit-keyframes resize {
0% { -webkit-transform: scale3d(0%, 0%, 1); }
90% { -webkit-transform: scale3d(100%, 100%, 1); }
95% { -webkit-transform: scale3d(95%, 95%, 1); }
100% { -webkit-transform: scale3d(100%, 100%, 1); }
}

Try to add -webkit-transform:transform to the bubble css

Related

Poor CSS Animation performance - no browser paints

I've got a number of elements that I'm animating which I've developed in a manner that shouldn't cause any browser paints. If I turn on "Paint Flashing" in Chrome Devtools I don't see any paint flashing at all. However, if I record the performance then the graph shows that there is a lot of time spent on painting. The FPS is as low as 15fps at times.
I actually built this in Vue, and the compiled code results in too much code to paste here. I realise the animation is somewhat broken, I still need to work out some timings etc - but for the purpose of this question, I'm only concerned about the performance.
I have posted the compiled code here on CodePen:
https://codepen.io/IOIIOOIO/pen/gjBqyg
It seems StackOverflow requires that I post some code here, so here is the compiled code for just one element:
.circle {
position: relative;
width: 100%;
padding-top: 100%;
border-radius: 50%;
overflow: hidden;
}
.circle::before {
content: "";
background-color: black;
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 100%;
animation-name: switch;
animation-iteration-count: infinite;
animation-timing-function: steps(1);
animation-duration: 3s;
animation-delay: inherit;
}
.rotating-circle {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
}
.rotating-circle--first-cycle {
background-color: black;
animation-name: rotate, toggle-first;
animation-duration: 3s, 3s;
animation-iteration-count: infinite, infinite;
animation-timing-function: linear, steps(1);
animation-delay: 1800ms;
}
.rotating-circle--second-cycle {
opacity: 0;
animation-name: rotate, toggle-second;
animation-duration: 3s, 3s;
animation-iteration-count: infinite, infinite;
animation-timing-function: linear, steps(1);
animation-delay: 1800ms;
}
#keyframes rotate {
0% {
transform: rotate3d(0, 1, 0, 0deg);
}
50% {
transform: rotate3d(0, 1, 0, 180deg);
}
}
#keyframes toggle-first {
0% {
opacity: 1;
}
25% {
opacity: 0;
}
75% {
opacity: 1;
}
}
#keyframes toggle-second {
0% {
opacity: 0;
}
25% {
opacity: 1;
}
75% {
opacity: 0;
}
}
#keyframes switch {
0% {
transform: translatex(0);
}
50% {
transform: translatex(100%);
}
100% {
transform: translatex(0);
}
}
<div class="circle" style="background-color: rgb(255, 0, 0); animation-delay: 0ms;">
<div class="rotating-circle rotating-circle--first-cycle" style="animation-delay: 0ms;">
</div>
<div class="rotating-circle rotating-circle--second-cycle" style="background-color: rgb(255, 0, 0); animation-delay: 0ms;">
</div>
</div>
It seems that all the work was being done on Composite Layers, and not necessarily on Painting alone. I found that adding transform: translateZ(0) or will-change to the individual elements that were being animated didn't help much. However, if I add transform: translateZ(0) to the parent .circle element then the time spent on Composite Layers and Painting is greatly reduced.
It still runs fairly slow but I think that may just be because my computer has onboard graphics and 4GB of RAM.
So I think this is as good as it will get but would appreciate any further suggestions.
Here is an example where I've added transform: translateZ(0) to the parent element:
https://codepen.io/IOIIOOIO/pen/gjBqyg
EDIT:
I've found a significant improvement by removing border-radius on the parent, which I had set to overflow: hidden to create a mask:
Before:
.circle {
border-radius: 50%;
overflow: hidden;
}
Instead, I used clip-path as a mask:
After
transform: translateZ(0);
clip-path: circle(49% at 50% 50%);
I'm sure you'll notice straight away it's much better:
https://codepen.io/IOIIOOIO/pen/OwBBJV
Any further insight into why this works would be much appreciated.

bouce effect not working on mozilla firefox

I work on bouce effect and i would like to know why this example doesn't work on firefox ???
http://jsfiddle.net/Nath/34eMN/
css part:
div { -webkit-animation: bounce 1.5s infinite ease-in-out; }
#-webkit-keyframes bounce {
0%, 20%, 60%, 100% { -webkit-transform: translateY(0); }
40% { -webkit-transform: translateY(-10px); }
80% { -webkit-transform: translateY(-5px); }
}
Because all your transforms are specified to webkit which is not Firefox. Remove the -webkit- part and see what happens. Firefox does not need prefixes and only webkit browsers do.

CSS3 image transitioning without hover

I am trying to find a transitioning CSS code to transition two images. I want the first image to be shown for 4 seconds then fade into a second image which will stay the same for for seconds then fade back to the first. Right now I am not using CSS and am finding most CSS tutorials are formatted for an on :hoover. I want my image to constantly change without a :hover being needed.
The flexi ad coding I am using now is a ans works fine in waterfox and explorer but you can see the images being loaded in chrome with a bad flicker.
Here's the example of what I am working with. The script I am using now is actually transitioning through 30 images i made some that fade from one to the next and thats why it looks like it fades. I would like some kind of CSS that will only require 2 images and fade one to the next every 4 seconds.
http://www.vulgarmediaproductions.com/walt/walt.shtml
You need to use keyframe animations for this - DEMO
HTML:
<img src='http://imgsrc.hubblesite.org/hu/db/images/hs-2012-10-a-web.jpg'>
<img src='http://imgsrc.hubblesite.org/hu/db/images/hs-2004-45-a-web.jpg'>
CSS:
img {
position: absolute;
width : 320px;
height: 180px;
}
img:last-child { animation: fader 4s infinite alternate; }
#keyframes fader { to { opacity: 0; } }
EDIT
If your images have transparency, then you'll need to animate the opacity for both of them, not just for the one on top. Like this - DEMO
img {
opacity: 0;
position: absolute;
width : 256px;
height: 256px;
}
img:first-child { animation: fadein 8s infinite alternate; }
img:last-child { opacity: 1; animation: fadeout 8s infinite alternate; }
#keyframes fadein { 50% { opacity: 1; } }
#keyframes fadeout { 50% { opacity: 0; } }
Also, keep in mind that you'll have to use prefixes (I did not use any since dabblet includes -prefix-free and it's easier to highlight the idea that way):
img:first-child {
-webkit-animation: fadein 8s infinite alternate; /* Chrome, Safari, Android, Blackberry */
-moz-animation: fadein 8s infinite alternate; /* FF, FF for Android */
-o-animation: fadein 8s infinite alternate; /* Opera 12 */
animation: fadein 8s infinite alternate; /* IE 10, FF 16+, Opera 12.5 */
}
#-webkit-keyframes fadein { 50% { opacity: 1; } }
#-moz-keyframes fadein { 50% { opacity: 1; } }
#-o-keyframes fadein { 50% { opacity: 1; } }
#keyframes fadein { 50% { opacity: 1; } }
/* same for the other set (fadeout) */
Not tested and just written on the fly, but should work.
If you have any problems getting it to work, let me know...
You may want to debug this using FireBug for Firefox. It helps you alot playing arround with CSS, HTML and JavaScript.
CSS3:
.slideShow
{
position: absolute;
left: 0;
top: 0;
-webkit-transition: all 200ms ease-in-out 0s;
-moz-transition: all 200ms ease-in-out 0s;
-ie-transition: all 200ms ease-in-out 0s;
-o-transition: all 200ms ease-in-out 0s;
transition: all 200ms ease-in-out 0s;
}
.slideShowWrapper { position:relative; }
HTML:
<div class="slideShowWrapper" id="mySlideShow" style="width:400px;height:300px;">
<div class="slideShow" style="opacity:1.0"> (image 1 goes here) </div>
<div class="slideShow" style="opacity:0.0"> (image . goes here) </div>
<div class="slideShow" style="opacity:0.0"> (image . goes here) </div>
<div class="slideShow" style="opacity:0.0"> (image N goes here) </div>
</div>
JS:
function ssCycle(_obj)
{
var _oList=_obj.getElementsByTagName('div');
for (var _trace=0;_trace<oList.length;_trace++)
{
if(_oList[_trace].getAttribute('style').indexOf('opacity:1.0')>0)
{
_oList[_trace].style.opacity='0.0';
try
{
_oList[(_trace+1)].style.opacity='1.0';
}
catch(_e)
{
_oList[0].style.opacity='1.0';
}
}
}
};
(function(_src){ void(var tmrFunc = "void(ssCycle(document.getElementById("+_src+"));";setInterval(tmrFunc,4000);}).call('mySlideShow');

CSS3 Rotating Animation with delay

Ok, so I have this rotating CSS3 animation (with a repeating timeout in the animation) almost working but I'm getting this really weird behavior where the animation seems to "jump" backward as it's animation.
I have a demo here in JS Fiddle (EDIT - Please excuse the long delay, it's a necessary part of the animation - a long timeout): http://jsfiddle.net/3mnMz/1/
For posterity, here is my CSS
#logo { position: relative; float: left; width: 175; height: 75px; margin: 0 0 16px; padding: 0; }
#-webkit-keyframes rotate {
0%, 65%, 75%, 100% {
-webkit-transform: rotate(0deg);
}
70% {
-webkit-transform: rotate(360deg);
-webkit-animation-timing-function: ease-in-out;
-webkit-animation-delay: 3s;
}
}
#logo span.star
{
-webkit-animation-name: rotate;
-webkit-animation-duration: 6s;
-webkit-animation-iteration-count: infinite;
}
#logo span.star { width: 84px; height: 84px; background: url('../img/logo_star.png') no-repeat left top; position: absolute; top: -8px; right: -20px; display: block;
}
Can someone shed some light on the subject?
I'm not sure about what you're trying to achieve, but the reason why it's rotating back and forth is because you're stating at keyframe 70% that the rotation is 360, then at 75 that it's rotation 0, so it goes back to the original state.
The animation properties should also be stated within the span.star element, not within the keyframes.
Here is a demo:
http://jsfiddle.net/3VrjE/

css3 animation on :hover; force entire animation

I've created a simple bounce animation which i'm applying to the :hover state of an element:
#keyframes bounce {
0% {
top: 0;
animation-timing-function: ease-out;
}
17% {
top: 15px;
animation-timing-function: ease-in;
}
34% {
top: 0;
animation-timing-function: ease-out;
}
51% {
top: 8px;
animation-timing-function: ease-in;
}
68% {
top: 0px;
animation-timing-function: ease-out;
}
85% {
top: 3px;
animation-timing-function: ease-in;
}
100% {
top: 0;
}
}
.box:hover {
animation: bounce 1s;
}
The animation works fine, with the exception that when you remove your cursor from the element it abruptly stops. Is there anyway to force it to continue the set number of iterations even if the mouse has exited? Basically what I'm looking for here is an animation triggered by the :hover state. I'm not looking for a javascript solution. I haven't seen anyway to do this in the spec, but maybe there's an obvious solution I've missed here?
Here's a fiddle to play with: http://jsfiddle.net/dwick/vFtfF/
I'm afraid that the only way to solve this is with a bit of javascript, you must add the animation as a class and then remove it when the animation finishes.
$(".box").bind("webkitAnimationEnd mozAnimationEnd animationend", function(){
$(this).removeClass("animated")
})
$(".box").hover(function(){
$(this).addClass("animated");
})
http://jsfiddle.net/u7vXT/
I created a JsFiddle with this answer from the same post https://stackoverflow.com/a/7697786/8335898 using pure Javascript if anyone wants to use it.
const elements = document.getElementsByClassName('box');
for (let i = 0; i <= elements.length; i++) {
elements[i].addEventListener('animationend', function(e) {
elements[i].classList.remove('animated');
});
elements[i].addEventListener('mouseover', function(e) {
elements[i].classList.add('animated')
})
}
Same answer with #methodofaction but for anyone using React:
import React, { useState } from 'react';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
export default function Icon({ icon }) {
const [animated, setAnimated] = useState(false);
return (
<div
onMouseEnter={() => setAnimated(() => true)}
onAnimationEnd={() => setAnimated(() => false)}
>
<FontAwesomeIcon icon={icon} className={animated ? 'animated' : ''} />
</div>
);
}
just to improve Duopixel answer, when runnig infinite animitation I have to do:
$(".box").css("animation-iteration-count", "1");
$(".box").bind("webkitAnimationEnd mozAnimationEnd animationEnd", function(){
$(this).removeClass("animated")
})
$(".box").hover(function(){
$(".box").css("animation-iteration-count", "infinite");
$(this).addClass("animated");
})
This just not abruptly end the animation.
A simple trick will do the job :
-webkit-animation:swing 3600ms ease-in-out 6000s;
-webkit-transform-origin:top;
Set the 'delay' with an high value on the element (not :hover).
From: Stackoverflow - Robert McKee
This won't work in all situations, and won't work for OP without some compromises but I solved this problem by adding an animation to the :not(:hover) selector:
#keyframes stopBounce {
0% {
top: 15px;
}
100% {
top: 0px;
}
}
#keyframes bounce {
ops: bounce code
}
.box{
top: 0px;
transition: top 250ms 1000ms ease-in-out,
}
.box:hover{
animation-name: bounce;
animation-fill-mode: both;
animation-duration: 250ms;
}
.box:not(:hover){
animation-name: stopBounce;
animation-duration: 250ms;
animation-delay: 1000ms;
animation-fill-mode: both;
}
So, what this doesn't do is allow the animation to continue all the way through. As far as I can tell a pure CSS solution to that is impossible. What it does do is allow it to smoothly transition back to it's starting position. The trick is having two selectors, only one of which can be active at any one time.
What this allows us to do is have an animation that plays when the user hovers, and a separate animation that plays whenever the user stops hovering. Since both of these animations can be controlled, it allows us to ensure that the transition between them is smooth.
Like I said, this doesn't fully solve the problem, but it doesn't use JavaScript and will keep things smooth.
CSS might help in some cases but not all, below is the code that will animate letter spacing on both hover and after hover.
h1
{
-webkit-transition:all 0.3s ease;
}
h1:hover
{
-webkit-transition:all 0.3s ease;
letter-spacing:3px;
}
<body>
<h1>Hello</h1>
</body>

Resources