How do you spin side to side using css3 animation? - css

I have an image of a face. I want to spin/rotate it side to side. 20 degrees to the right and 20 degrees to the left.
So far this is my code:
<img class="image">
CSS
.image {
-webkit-animation:spin 1.8s linear infinite;
}
#-webkit-keyframes spin {
from { -webkit-transform: rotate(0deg); }
to { -webkit-transform: rotate(20deg); }
}
I can get it to move one way, but how do I make it go back the other way?
I was thinking it should work like this: spin from 0 deg to 20 deg from 20 deg to -20 degrees. I tried it but it doesn't work.

You would not be able to achieve it using from and to in animations but you can use the percentage option like below:
#-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(20deg);
}
100% {
-webkit-transform: rotate(-20deg);
}
}
Explanation:
For the first 50% of the animation duration (0-0.9s), it would rotate the image from 0 to 20 degrees.
For the next 50% (50% - 100%), it would rotate the image from 20 degrees to -20 degrees.
For the animation to have a more smoother look, you could also a rotate to 0 degree in between and at the end (as shown in Sample 2 below).
If you want 0 to 20 alone to happen in a 1.8s window and 20 to -20 degrees to take another 1.8s then you can increase the animation duration to 3.6s in the -webkit-animation property value like below (at the end).
Note: I assume you are aware that with the -webkit- prefix, the animation effect would be seen only in webkit powered browsers. For Firefox, you would have to add -moz- for the animations, keyframes and transform properties and for future compliance you would have to add the standard un-prefixed versions also.
.image {
-webkit-animation:spin 3.6s linear infinite;
}
Fiddle Demo
Sample 2 - with a smoother rotation effect
#-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
25% { /* note that rotation from 0 to 20 deg happens in 25% time = 0.45 seconds. */
-webkit-transform: rotate(20deg);
}
50% {
-webkit-transform: rotate(0deg);
}
75% {
-webkit-transform: rotate(-20deg);
}
100% {
-webkit-transform: rotate(0deg);
}
}
Demo for Sample 2

Related

Safari transforms SVG wrong

I made a little CSS animation with a simple svg to transition my hamburger menu to a cross. It works as expected on Chrome and Firefox, but the translation is off in Safari. The animation plays, and even resets correctly so it has nothing to do with prefixes (I tried). The translate of the two lines making the cross is just wrong.
I'm guessing it has something to do with how safari handles the transform when scaling is also applied. Does anyone know if there is a work around / or what I'm doing wrong?
JSFiddle
Safari / Firefox / Chrome
#keyframes showCross {
0% {
transform: scale(1) rotate(0);
}
40% {
transform: scale(0.3) rotate(280deg);
}
100% {
transform: scale(1) rotate(360deg);
}
}
#keyframes showCross_P1 {
0% {
transform: rotate(0);
}
100% {
transform: rotate(-45deg) translate(-42%, -10%);
}
}
I fixed it by doing the following:
First I removed the groups surrounding the paths.
Then I gave all the paths the following values:
transform-origin:center center;
transform-box: fill-box;
Next I edited the animation keyframes to look as follows:
0% {
transform: translate(0rem,0rem) rotate(0);
}
100% {
transform: translate(-10rem,-38rem) rotate(-45deg) ;
}
Safari has problems with percents and also if you put the rotation before the translate it has inconsistency with other browsers, use rem instead!

Safari CSS Bug: Animation Rotation Direction Incorrect?

I'm writing a custom animation for a project I'm working on. The idea is that the animation is meant to resemble an exclamation mark becoming unhinged from the baseline, swinging for a moment, and then falling off the baseline entirely.
For some reason, only Safari (OSX and iOS) refuses to render the first animation keyframe as a clockwise rotation in a CSS animation I've made. Instead, it renders the keyframe as a counter-clockwise animation, but then works just fine for the following animation keyframes.
Working CodePen example: http://codepen.io/michaelmarcialis/pen/obPYPO
#keyframes unhinged {
0% {
transform: rotate(0deg);
}
15% {
transform: rotate(240deg);
}
30% {
transform: rotate(125deg);
}
45% {
transform: rotate(220deg);
}
60% {
transform: rotate(145deg);
}
75% {
opacity: 1;
transform: rotate(200deg);
}
90% {
opacity: 0;
transform: translate(-0.5rem, 8.57142857142857rem) rotate(215deg);
}
95% {
opacity: 0;
transform: translate(0) rotate(0deg);
}
100% {
opacity: 1;
transform: rotate(0deg);
}
}
All other browsers render the animation as intended, with the first animation keyframe rotating clockwise. Safari is the only one that applies a counter-clockwise rotation in the initial keyframe. I'm assuming Safari is doing this because the distance to travel the rotation is shorter when going counter-clockwise, but it's not honoring the CSS spec properly if that's the case.
Does anyone know a remedy for this?
The problem is that if you try to animate a rotate in safari greater than 180 degrees, it will instead rotate the other way. So if you try to rotate +270 degrees, Safari will animate a rotation of -90 degrees.
The workaround for Safari is to never rotate more than 179 in either direction, then complete the rest of the rotation in another segment.

Direction of rotation in CSS Animation\Transformation

I'm trying to understand CSS animations and I'm running into the following issue:
I've got a simple div with animation attached to it in CSS, like below:
<div id="learn">LEARN</div>
#learn {
width: 100px;
height: 100px;
background: blue;
position: relative;
animation: test1 5s ease-in 2s infinite;
}
Case 1:
#keyframes test1 {
0% {
transform: rotate(179deg);
}
100% {
transform: rotate(357deg);
}
}
Case 2 (the 0% transform is split into 90+89 deg instead of 179):
#keyframes test1 {
0% {
transform: rotate(90deg) rotate(89deg);
}
100% {
transform: rotate(357deg);
}
}
Why is the first case rotating clockwise and the second case rotating counter clockwise?
This might just be a bug with rotation transforms, which I'll address after some background.
Background
First off, the way rotations are supposed to work is with relation to a circle. If you specify a number of degrees, that will place the element in the position dictated by a how much rotation the degrees specify. When not animating a rotation, there are many ways to represent the element's placement. Code Uniquely is half-right in their comment in that the placement of 357 degrees and -3 degrees is the same, but when animating, they're very different. Going from 0 degrees to -3 degrees is a small counter-clockwise rotation, whereas going from 0 degrees to 357 degrees is a large clockwise rotation.
Findings
What you've found seems to ignore this calculation (in both Firefox and Chrome from what I've tested out). From what I'm seeing, combining rotate transforms effectively reverses the direction that the rotation should be going in, even if you're combining with a 0deg rotation:
transform: rotate(90deg); //rotates clockwise
transform: rotate(0deg) rotate(90deg); //rotates counter-clockwise
It seems that you can fix this by "combining" the rotation transforms in both animation steps:
// this performs a clockwise rotation
#keyframes test3 {
0% {
transform: rotate(0deg) rotate(90deg);
}
100% {
transform: rotate(0deg) rotate(357deg);
}
}
Finally, it seems that the number of "combinations" matters. If you combine 2 rotations in one step, but 3 in another, the unexpected behavior occurs:
// rotates counter-clockwise since there are unequal rotation transforms
#keyframes test4 {
0% {
transform: rotate(0deg) rotate(0deg) rotate(90deg);
}
100% {
transform: rotate(0deg) rotate(357deg);
}
}
Conclusion
This likely isn't the greatest answer, but combining rotations like this just doesn't appear to be documented anywhere. I would suggest not combining the same rotate transforms (you can still combine rotateX and rotateY without this weirdness) and stick with the sum of the degree values.
In case anyone finding this explanation wants to perhaps find out more about this behavior than I have, here's a fiddle with the examples above as a starting point.

Replace #keyframes in css with transitions

The platform were I work does not support #keyframes because of security reasons with the #.
My question is if I can replace it with some other css trick.
For example I have this code:
.cubo {
animation:giro 25s infinite linear;
}
#keyframes giro {
0% {transform: rotateX(0deg) rotateY(0deg);}
100% {transform: rotateX(1080deg) rotateY(360deg);
}
}
Can I replace it with transitions or transforms to avoid using the #? (no javascript supported either).
You could instead make it a transition by multiplying the transition duration, rotateX, and rotateY values all by a common factor x and applying the transition class on page load. In my example I multiplied them by 40, but you can go as high as you want but I wouldn't go too high because the processor might overload at some point and break the page. This runs for 1000 seconds, not many people will stay on a page past that
Here is a live demo of that approach
/* CSS */
.cubo {
/* ...Your other code... */
transition: all 1000s linear;
}
.animate {
-webkit-transform: rotateX(43200deg) rotateY(14400deg);
-moz-transform: rotateX(43200deg) rotateY(14400deg);
-o-transform: rotateX(43200deg) rotateY(14400deg);
-ms-transform: rotateX(43200deg) rotateY(14400deg);
transform: rotateX(43200deg) rotateY(14400deg);
}
/* Javascript (ran on page load) */
document.getElementsByClassName('cubo')[0].classList.add('animate');

Have CSS3 spin start slow then end slow?

This is not a question that can be solved by using ease-in.
If I have an element that I want to spin in CSS3 for a certain amount of time, but that starts off slow and ends slow, how can I do this?
CSS
#-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
div{
background-image:-webkit-radial-gradient(center, ellipse cover, rgba(0,0,0,1) 0%,rgba(51,51,51,1) 20%,rgba(0,0,0,1) 20%,rgba(51,51,51,1) 40%,rgba(0,0,0,1) 40%,rgba(51,51,51,1) 60%,rgba(0,0,0,1) 60%,rgba(51,51,51,1) 80%,rgba(0,0,0,1) 80%,rgba(51,51,51,1) 100%);
width: 200px;
height: 200px;
-webkit-animation-name: spin;
-webkit-animation-duration: 2s;
-webkit-animation-iteration-count: 60.5;
-webkit-animation-timing-function: ease-in;
}
HTML
<div></div>
I can't seem to figure out how to do this. My animation runs for a total of 121 seconds, since it takes 2 seconds for one spin to complete, so 60.5 spins will take a total of 121 seconds (if my math is incorrect, please tell me). This works fine, except that I want the div to start spinning off slow, then completed all 59 rotations, then end slow for the last one.
I'd like to use pure CSS for this, if possible.
Sorry that I don't have a JSFiddle...
Edit: I used a relative solution in my experiment: CSS3 Clock, could that count as a half fiddle? :D
Edit #2: JSFiddle provided by #Charlie: http://jsfiddle.net/7DPnc
If it really has to be pure CSS, I would suggest wrapping 3 divs together and spin them separately:
CSS
div.first_round
{
-webkit-animation-duration:3s;
-webkit-animation-iteration-count:1;
}
div.last_round
{
-webkit-animation-duration:3s;
-webkit-animation-iteration-count:1.5;
-webkit-animation-delay:100s; /* you'll have to do the math */
}
div.main_round
{
-webkit-animation-duration:2s;
-webkit-animation-delay:3s;
-webkit-animation-iteration-count:59;
-webkit-animation-timing-function:linear;
}
HTML
<div class="first_round">
<div class="last_round">
<div class="main_round">
</div>
</div>
</div>
Or if you don't mind using a little JS, listen to animationend event...
You need 60 spins in 120 seconds right?
Lets first change the iteration count to 1.
-webkit-animation-iteration-count:1;
and the duration to 120 seconds
-webkit-animation-duration: 120s;
Now set the amount of spins. (360deg x 60spins)
#-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(21600deg); }
}
And now we'll modify that to set the timing. (shave a rotation off each side, add to new section)
#-webkit-keyframes spin {
10% { -webkit-transform: rotate(360deg); }
90% { -webkit-transform: rotate(20880deg); }
100% { -webkit-transform: rotate(21600deg); }
}
Lastly, we set the easing function to linear in order to avoid the stop that will occur between keyframe sections if you use a curve. (replace with ease, ease-out, etc to see what I mean)
-webkit-animation-timing-function: linear;
You can easily tweak the timing by changing duration, and the keyframe percentages.
DEMO

Resources