I've been stuck on this problem for 3 days and have scoured the Internet for a solution, but haven't been able to find one that works yet.
I have an animation of a cartoon rocket flying across a screen. The rocket has 4 chained keyframe animations applied to it:
1.) "launch" moves the rocket from off the left side of the screen, across to the right
2.) "rightself" rotates the rocket so it's pointing up
3.) "descend" moves the rocket down towards a planet
4.) "shrink" makes the rocket smaller as it approaches the planet's surface
I can't add a video here, but here are links to how it should and shouldn't look:
How it should look:
https://twitter.com/planet_katie/status/1415739110505996291
How it's glitching on all iOS browsers and desktop Safari:
https://twitter.com/planet_katie/status/1418312787906998275
Game Link, if you want to try yourself: http://www.codeeverydamnday.com/projects/rocketblaster/index.html
The rocket animation runs smoothly on desktop Chrome and Firefox, but glitches in Safari. It also runs smoothly on Android phones, but again glitches on every browser I've tried on an iPhone. The iPhone emulator in Chrome's dev tools shows it running smoothly as well, so I'm not sure why it's not translating to the iPhone itself.
Things I have tried:
Changing my svg images to png's, as I read that sometimes svg's behave unexpectedly
Added all of the proper -webkit- prefixes
Condensing the 4 animations into 1
Using the longhand format when adding my CSS animation on my element (animation-name, animation-duration, animation-iteration-count, etc) instead of the shorthand format
Including both the 0% and 100% keyframes for each animation
Adding a 0.01 second delay to the first animation (read somewhere that this helped someone else)
So far, no luck. Anyone able to take a look at my code and see if I'm missing anything? Note: I have removed the -moz-, -ms- and -o- prefixes for brevity, but they are in my code as well.
#rocketfire {
background-color: red;
position: absolute;
top: 100px;
left: -320px;
height: 200px;
-webkit-animation: launch 4s ease-in-out 0.01s 1 forwards,
rightself 2s ease-in-out 3.5s 1 forwards,
shrink 3.5s ease-in-out 4s 1 forwards, descend 4s ease-in-out 5s 1 forwards;
animation: launch 4s ease-in-out 1 forwards,
rightself 2s ease-in-out 3.5s 1 forwards,
shrink 3.5s ease-in-out 4s 1 forwards, descend 4s ease-in-out 5s 1 forwards;
}
#-webkit-keyframes launch {
0% {
-webkit-transform: translateX(-0px);
}
100% {
-webkit-transform: translateX(1050px);
}
}
#keyframes launch {
0% {
transform: translateX(-320px);
}
100% {
transform: translateX(1050px);
}
}
#-webkit-keyframes rightself {
0% {
-webkit-transform: translateX(1050px) rotate(0deg);
}
100% {
-webkit-transform: translateX(1050px) rotate(-82deg);
}
}
#keyframes rightself {
100% {
transform: translateX(1050px) rotate(-82deg);
}
}
#-webkit-keyframes descend {
0% {
-webkit-top: 0px;
}
100% {
-webkit-top: 270px;
}
}
#keyframes descend {
100% {
top: 270px;
}
}
#-webkit-keyframes shrink {
0% {
-webkit-transform: translateX(1050px) rotate(-82deg) scale(1);
}
100% {
-webkit-transform: translateX(1050px) rotate(-82deg) scale(0.5);
}
}
#keyframes shrink {
100% {
transform: translateX(1050px) rotate(-82deg) scale(0.5);
}
}
<img id="rocketfire" src="images/rocketfireright.png" />
I think you shouldn’t need the -webkit versions of the animations, so removing those will make the CSS easier to debug. I found a couple of inconsistencies and missing values. Cleaned up, the CSS looks like the following:
#rocketfire {
background-color: red;
position: absolute;
top: 100px;
left: -320px;
height: 200px;
animation: launch 4s ease-in-out 1 forwards,
rightself 2s ease-in-out 3.5s 1 forwards,
shrink 3.5s ease-in-out 4s 1 forwards,
descend 4s ease-in-out 5s 1 forwards;
}
#keyframes launch {
0% {
transform: translateX(-320px);
}
100% {
transform: translateX(1050px);
}
}
#keyframes rightself {
0% {
transform: translateX(1050px) rotate(0deg);
}
100% {
transform: translateX(1050px) rotate(-82deg);
}
}
#keyframes descend {
0% {
top: 0px;
}
100% {
top: 270px;
}
}
#keyframes shrink {
0% {
transform: translateX(1050px) rotate(-82deg) scale(1);
}
100% {
transform: translateX(1050px) rotate(-82deg) scale(0.5);
}
}
Try that and see if it fixes it!
What ultimately worked for me was combining the four animations into one, like this:
#keyframes launch {
30% {transform: translateX(1050px) rotate(0);}
50% {transform: translateX(1050px) scale(1) rotate(-82deg); top: 100px;}
80% {transform: translateX(1050px) scale(0.5) rotate(-82deg);}
100% {transform: translateX(1050px) scale(0.5) rotate(-82deg); top: 270px;}
}
Seems like Safari had a problem trying to run multiple keyframes animations at once.
Related
Is it possible to rotate an element using a condition with out using Javascript.
I basically want the hand to start moving when one of my innerHTML elements reaches a certain length. Also is it possible to stop the hand at 180 degrees instead of it going back to its starting point.
Thanks :)
See code below:
.hand {
width: 20px;
height: 190px;
background-color: #005bdb;
position: absolute;
left: 0;
transform-origin: bottom;
-webkit-animation: spin 30s linear;
-moz-animation: spin 30s linear;
animation: spin 30s linear;
}
#-moz-keyframes spin {
100% {
-moz-transform: rotate(180deg);
}
}
#-webkit-keyframes spin {
100% {
-webkit-transform: rotate(180deg);
}
}
#keyframes spin {
100% {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
<div class="hand">
</div>
I want to flip an image instantly every 1000ms. I'm trying but the animation does what it's supposed to do (gradually flip the picture). If i can flip instantly the picture it will give the idea of a walking duck. I know I can use setInterval() but I'd rather do this in CSS only.
.duck {
position: absolute;
animation: flip-me;
animation-duration: 1000ms;
animation-direction: alternate;
animation-iteration-count: infinite;
}
#keyframes flip-me {
0% { transform: scaleX(1) }
100% { transform: scaleX(-1) }
}
You can consider steps()
img {
animation: flip-me 2s steps(1) infinite;
}
#keyframes flip-me {
50% { /*Pay attention: it's 50% not 100% !!*/
transform: scaleX(-1)
}
}
/*no need 0% or 100% state as they be set by default to scaleX(1)*/
<img src="https://picsum.photos/200/200?image=1069">
How can I repeat a spinning animation x times before easing it out ?
For instance :
#spin-please {
background: green;
width: 50px;
height: 50px;
animation: spin 3s infinite ease-in-out;
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
49% {
transform: rotate(359deg);
}
50% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<div id="spin-please">
</div>
My animation right now is not very smooth at all (as you can see between the 1st and 2nd rotation), and there is an easing between the 2 rotations, which I want only at the start of the first of the rotation and at the end of the second (or the third if I choose to go with an additional rotation).
Easing in ==> rotation 1 ==> rotation 2 ==> easing out
Is this doable with CSS ?
Instead of repeating the animation infinite times, you can specify a number of repetitions like this:
animation: spin 3s 3 ease-in-out; /* 3secs, repeat 3 times */
See animation iteration count for more examples.
Also useful to see the animation short-hand docs to set all the properties at once (like your code does)
I am not sure what the desired outcome you are looking for but I modified the animation to display the spinning happening three times (with some reversal spin as well)
#spin-please {
background: green;
width: 50px;
height: 50px;
/* #keyframes duration | timing-function | delay |
iteration-count | direction | fill-mode | play-state | name
*/
animation: 1s 3 spin;
animation-timing-function: ease-in, linear, ease-out;
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
<div id="spin-please">
</div>
The problem is totally not because your animation isn't smooth,
the problem with keyframes, according to this code
49% {
transform: rotate(359deg);
}
50% {
transform: rotate(0deg);
}
Your animation have to do 360deg rotation in very short time which is 1% ( between 49% - 50%) for any animation-timing-function value your animation is not smooth, Try this code :
#spin-please {
background: green;
width: 50px;
height: 50px;
animation: spin 3s ease infinite;
}
#keyframes spin {
0% {
animation-timing-function: ease-out;
transform: rotate(0deg);
}
50% {
transform: rotate(180deg);
}
100% {
animation-timing-function: ease-in;
transform: rotate(360deg);
}
}
<div id="spin-please">
</div>
Remember you can change your animation-timing-function in your keyframes. more details about animation-timing-function.
#spin-it {
background: green;
width: 50px;
height: 50px;
animation: spin 1.5s ease infinite;
}
#keyframes spin {
0% {
animation-timing-function: ease-out;
transform: rotate(0deg);
}
25% {transform: rotate(90deg);}
50% {
transform: rotate(180deg);
}
75% {transform: rotate(270deg);}
100% {
animation-timing-function: ease-in;
transform: rotate(360deg);
}
}
<div id="spin-it">
</div>
My version of MMJ's
It goes through 5 steps.
Ease in >>> Turn 1 side >>> Turn 1 side >>> Turn 1 side >>> Turn 1 side >>> Ease out
I have an animation that works fine on Firefox, Chrome but does not work on Safari and Edge.
The animation objects are contained in a svg file loaded with js.
The idea is that elements appear in succession at the center of screen and then move up to their intended final location.
An example of the css I use to achieve this is:
#-webkit-keyframes move-you {
0% {
opacity: 0;
-webkit-transform: translate(450px,400px);
transform: translate(450px,400px);
}
50% {
opacity: 1;
-webkit-transform: translate(450px,400px);
transform: translate(450px,400px);
}
100% {
opacity: 1;
-webkit-transform: translate(450px,222px);
transform: translate(450px,222px);
}
}
#keyframes move-you {
0% {
opacity: 0;
-webkit-transform: translate(450px,400px);
transform: translate(450px,400px);
}
50% {
opacity: 1;
-webkit-transform: translate(450px,400px);
transform: translate(450px,400px);
}
100% {
opacity: 1;
-webkit-transform: translate(450px,222px);
transform: translate(450px,222px);
}
}
.svgLoaded #you {
-webkit-animation: move-you 1s ease-in 3s;
animation: move-you 1s ease-in 3s;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
So, this works fine on Firefox and Chrome but the translation does not happen in Safari and Edge. Not a massive problem if large screen are used as everything is still visible,
( you can see example here )
but it means that I cannot translate items to where I want them on a small screen.
I have been stack on this for more than a day, the only answer I found was about missing brackets but I checked my code and all brackets are balanced. Any help would be really appreciated.
I think this would probably work:
#-webkit-keyframes move-you {
0% {
opacity: 0;
-webkit-transform: translate(450px,400px);
}
50% {
opacity: 1;
-webkit-transform: translate(450px,400px);
}
100% {
opacity: 1;
-webkit-transform: translate(450px,222px);
}
}
#keyframes move-you {
0% {
opacity: 0;
transform: matrix(1,0,0, 1,0,0, 450, 400);
}
50% {
opacity: 1;
transform: translate(1,0,0, 1,0,0, 450, 400);
}
100% {
opacity: 1;
transform: translate(1,0,0, 1,0,0, 450, 222);
}
}
.svgLoaded #you {
-webkit-animation: move-you 1s ease-in 3s;
animation: move-you 1s ease-in 3s;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
There are a lot of problems with animating SVGs on different browsers. They all work different.
Here are some of the problems with creating consistent animations with SVGs:
IE and Opera don't honor CSS transforms at all on SVG elements. Instead, you must assign the value to the transform attribute.
Firefox didn't honor %-based origins in early versions (in latest versions it does).
Zooming in Safari breaks the sync between %-based and px-based origins.
Firefox doesn't recognize keyword-based origins like "right bottom", and Safari alters them when the zoom is anything but 100%.
In all browsers, px-based origins are measured differently for SVG elements than other DOM elements (see below).
quotation of document on SVG transformations in css-tricks
I found that using libraries like TweenMax do a pretty good work with almost all the browsers.
Of course there are some specific ways you should animate some of the properties so that they can work on IE 11. Few of them:
- Circle radius
- transitions
You can check the tips and tricks for the tool in css-tricks:
I have a bit of CSS3 animation which works perfectly in all the browser which support CSS3 except safari. Weird isn't it? Ok here's my code:
HTML
<div class="right">
<div class="key-arm"><img src="images/landing/key-arm.png" alt="arm" /></div>
</div>
CSS
.landing .board .right {
width: 291px;
height: 279px;
background: url('../images/landing/key-pnl.png');
bottom: 16px;
right: 250px;
position: absolute;
}
.landing .board .right .key-arm {
position: absolute;
left: 44px;
top: 18px;
width: 41px;
height: 120px;
}
/*=== Key Arm Animation ===*/
#-webkit-keyframes keyarm {
0% { -webkit-transform: rotate(0deg); }
5% { -webkit-transform: rotate(-14deg); }
10% { -webkit-transform: rotate(0deg); }
}
#-moz-keyframes keyarm {
0% { -moz-transform: rotate(0deg); }
5% { -moz-transform: rotate(-14deg); }
10% { -moz-transform: rotate(0deg); }
}
#-ms-keyframes keyarm {
0% { -ms-transform: rotate(0deg); }
5% { -ms-transform: rotate(-14deg); }
10% { -ms-transform: rotate(0deg); }
}
#-o-keyframes keyarm {
0% { -o-transform: rotate(0deg); }
5% { -o-transform: rotate(-14deg); }
10% { -o-transform: rotate(0deg); }
}
#keyframes keyarm{
0% { transform: rotate(0deg); }
5% { transform: rotate(-14deg); }
10% { transform: rotate(0deg); }
}
.right .key-arm{
-webkit-transform-origin: 12px 105px;
-moz-transform-origin: 12px 105px;
-ms-transform-origin: 12px 105px;
-o-transform-origin: 12px 105px;
transform-origin: 12px 105px;
-webkit-animation: keyarm 8s ease-in-out 0s infinite;
-moz-animation: keyarm 8s ease-in-out 4s infinite;
-ms-animation: keyarm 8s ease-in-out 4s infinite;
-o-animation: keyarm 8s ease-in-out 4s infinite;
animation: keyarm 8s ease-in-out 0s infinite;
}
Ok this doesn't work in Safari as I said, there's no movement whatsoever.
Also, still and only in Safari, the key-arm div shows only if you resize the screen! It's there in the DOM but for some reason it doesn't show up!
What am I doing wrong?
Thanks
Mauro
UPDATE: Ok from your answers I got that #keyframes is not supported on Safari 4. It's strange because on the same page I have an animation that works using #keyframes!
here's the CSS code:
.board .rays{
background: url("../images/landing/rays.gif") no-repeat 0 0 red;
height: 381px;
left: 251px;
opacity: 1;
top: 80px;
width: 408px;
position: absolute;
}
.board .bottle{
background: url("../images/landing/bottle.gif") no-repeat 0 0 lime;
bottom: 30px;
height: 405px;
left: 276px;
width: 357px;
z-index: 1;
position:absolute;
}
/*=== Rays Animation ===*/
#-webkit-keyframes rays{
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
#-moz-keyframes rays{
0% { -moz-transform: rotate(0deg); }
100% { -moz-transform: rotate(360deg); }
}
.board .rays{
-webkit-animation: rays 40s linear 0s infinite;
-moz-animation: rays 40s linear 0s infinite;
animation: rays 40s linear 0s infinite;
}
And the html:
<div class="board">
<div class="rays"></div>
<div class="bottle"></div>
</div>
Try it yourself in jsFiddle (if you have Safari 4) and you'll see
Found the solution. In Safari when you use Keyframes you need to use the whole percentage:
this won't work:
#-webkit-keyframes keyarm {
0% { -webkit-transform: rotate(0deg); }
5% { -webkit-transform: rotate(-14deg); }
10% { -webkit-transform: rotate(0deg); }
}
this will:
#-webkit-keyframes keyarm {
0% { -webkit-transform: rotate(0deg); }
5% { -webkit-transform: rotate(-14deg); }
10% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(0deg); }
}
Don't know why but that's the way Safari works! :)
I was having troubles with CSS3 animation working in Safari 6, but not in Safari 4 (4.0.5).
It appears that the shorthand notation will not work in Safari 4.
So this won't work :
-webkit-animation: rays 40s linear forwards;
But this will work :
-webkit-animation-name: rays;
-webkit-animation-duration: 40s;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: linear;
-webkit-animation-fill-mode: forwards;
In situations where you're trying to animate transform on something as soon as it's injected into the DOM, I've had to add a very brief delay, like this:
animation: rays 40s linear 0.01s infinite;
I struggled with an animation working in Safari 14 (14.1.2), but not in Safari 15, and thought I'd add my findings here.
This css is part of the scrolling text loop here.
#banner-loop {
white-space: nowrap;
animation: loop-anim 5s linear infinite;
}
#keyframes loop-anim {
0% { margin-left: 0; }
100% { margin-left: -50%; }
}
I noticed that the animation "played", but didn't animate.
I tried the solutions from the other answers here, but nothing worked (including having the -webkit prefix). In the end the problem was solved by changing the start keyframe value to 0% instead of 0.
It looks like Safari can't handle the unit-less 0 shorthand in this case.
Try force quitting Safari and/or rebooting your phone (assuming you're on a phone).
Just had animations fail in Safari 15 for no apparent reason - very simple ones such as opacity and simple keyframes.
I noticed my phone was doing that thing where the white homescreen indicator gets permanently stuck on the long side of the phone even when holding it vertically. A reboot is usually needed to fix that.
Turns out rebooting also fixed the animations in Safari.
Another thing to remember with Safari is that low battery mode can affect animations and make them less smooth (and prevent muted autoplay videos from auto playing).
#-webkit-keyframes { <- let this symbol to the same line
} - >
This works on iphone 3 ios 6.1.6
with -webkit- prefix on transform and animation