I got 2 boxes (200px X 200px) and I want to animate them with CSS animation. First (upper box) need to animate from rotateX(0deg) to rotateX(90deg) and I use transform-origin: center top. And I want second box to follow the bottom line of first box so I animate this box from translateZ(0px) translateY(0px) to translateZ(200px) translateY(-200px). And this is good only in start and end of animation. Example is on this link Animation example.
How to do this so box won't fall apart in between of start and end of animation?
In example I use only -webkit- and -moz- prefix.
JSFIDDLE
HTML
<div class="box box-1"></div>
<div class="box box-2"></div>
CSS
body{
padding: 200px 0 0 0;
margin: 0;
background-color: orange;
-webkit-transform-style: preserve-3d;
-webkit-perspective: 1000px;
-moz-transform-style: preserve-3d;
-moz-perspective: 1000px;
}
.box{
height: 200px;
width: 200px;
margin: 0 auto;
-webkit-transform-origin: center top;
-moz-transform-origin: center top;
opacity: 0.7;
}
.box-1{
background-color: blue;
-webkit-animation-duration: 3s;
-webkit-animation-name: boxOne;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
-moz-animation-duration: 3s;
-moz-animation-name: boxOne;
-moz-animation-iteration-count: infinite;
-moz-animation-direction: alternate;
}
.box-2{
background-color: purple;
-webkit-animation-duration: 3s;
-webkit-animation-name: boxTwo;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
-webkit-animation-duration: 3s;
-webkit-animation-name: boxTwo;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
}
#-webkit-keyframes boxOne{
from {
-webkit-transform: rotateX(0deg);
}
to {
-webkit-transform: rotateX(90deg);
}
}
#-webkit-keyframes boxTwo{
from {
-webkit-transform: translateZ(0px) translateY(0px);
}
to {
-webkit-transform: translateZ(200px) translateY(-200px);
}
}
#-moz-keyframes boxOne{
from {
-moz-transform: rotateX(0deg);
}
to {
-moz-transform: rotateX(90deg);
}
}
#-moz-keyframes boxTwo{
from {
-moz-transform: translateZ(0px) translateY(0px);
}
to {
-moz-transform: translateZ(200px) translateY(-200px);
}
}
That is quite a complicated animation. You may want to look into different easing methods for the translation. If you simplify the problem onto a 2D plane the top element height is increasing but the rate of growth increases over time. You can apply easing to the animation of the second element to mimic this increase over time. See if any of these help: http://easings.net/ The easeInCirc is probably the closest to (if not exactly) what you need.
Related
I'm wondering if it's possible to perform a CSS transition where an image does this:
Begins on the left.
Moves from the left, to the right.
When it reaches the right hand side, it flips horizontally, and then
moves back towards the left again.
When it reaches the left, it flips horizontally again and moves
towards the right side, and so on.
So far I have this fiddle: https://jsfiddle.net/kkn7cpqL/1/
This:
animation-direction: alternate;
is moving the image back and forth correctly, but I don't know how to make it flip once it reaches the sides. I'd like the arrow to always be pointing in the direction it's moving.
Any help with this would be really appreciated, thanks!
Try this code
This might help you to achieve what you want.
#keyframes arrow {
0% {
left: 0%;
transform: rotateY(0deg);
}
49% {
transform: rotateY(0deg);
}
50% {
left: 90%;
transform: rotateY(180deg);
}
99% {
transform: rotateY(180deg);
}
100% {
left: 0%;
transform: rotateY(0deg);
}
}
div.arrow {
width: 44px;
height: 50px;
position: absolute;
animation-name: arrow;
animation-duration: 10s;
/* double of original time */
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
<div class="arrow">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvXxGWc9lfv_WXJ3RtUb-4pBMRDYZOG4b9YXNnNkNGOsImdDnN5w" />
</div>
Just make it flip on 0% and 100% in animation it will give you the required result. Or you can just simply copy the below code.
#keyframes arrow {
0% {left:50px; top:10px;-moz-transform: scaleX(-1);
-o-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
filter: FlipH;
-ms-filter: "FlipH";}
100% {left:250px; top:10px;-moz-transform: scaleX(1);
-o-transform: scaleX(1);
-webkit-transform: scaleX(1);
transform: scaleX(1);
filter: FlipH;
-ms-filter: "FlipH";}
}
div.arrow {
width: 44px;
height: 50px;
position: absolute;
animation-name: arrow;
background-repeat: no-repeat;
animation-duration: 3s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
<div class="arrow">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvXxGWc9lfv_WXJ3RtUb-4pBMRDYZOG4b9YXNnNkNGOsImdDnN5w"/>
</div>
Try this code
This might help you to achieve what you want
#keyframes arrow {
0% {left:50px; top:10px;}
50%{transform: rotateX(90deg);}
100% {left:250px; top:10px;}
}
div.arrow {
width: 44px;
height: 50px;
position: absolute;
animation-name: arrow;
background-repeat: no-repeat;
animation-duration: 3s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
http://codepen.io/ankitkothari225/pen/bpgRPo
I want pendulum effect with pure CSS but it's not smooth.
Here is what I want, but with pure CSS. http://www.webdevdoor.com/demos/html5-pendulum-demo/
But I prefer more looked like natural speed variation according to it's position.
Fiddle
.bellImg {
height: 20px;
width: 20px;
position: absolute;
right: 10px;
top: 18px;
-webkit-animation-name: rotate;
animation-delay: 3s;
-webkit-animation-duration: 2s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: linear;
-webkit-transform-origin: 50% 0%;
-webkit-animation-timing-function: ease-in-out;
}
#-webkit-keyframes rotate {
0% {
-webkit-transform: rotate(0deg);
}
10% {
-webkit-transform: rotate(10deg);
}
20% {
-webkit-transform: rotate(20deg);
}
30% {
-webkit-transform: rotate(10deg);
}
40% {
-webkit-transform: rotate(5deg);
}
50% {
-webkit-transform: rotate(0deg);
}
60% {
-webkit-transform: rotate(-5deg);
}
70% {
-webkit-transform: rotate(-10deg);
}
80% {
-webkit-transform: rotate(-20deg);
}
90% {
-webkit-transform: rotate(-10deg);
}
100% {
-webkit-transform: rotate(0deg);
}
}
<img class="bellImg" src="img/bell.png">
There are a few problems in your code:
The animation-timing-function is specified as ease-in-out. This indicates that the animation starts and end slowly but has more speed in between. For a graceful and equal move, this should be set to linear.
This is what MDN says about ease-in-out timing function:
This keyword represents the timing function cubic-bezier(0.42, 0.0, 0.58, 1.0). With this timing function, the animation starts slowly, accelerates then slows down when approaching its final state. At the beginning, it behaves similarly to the ease-in function; at the end, it is similar to the ease-out function.
There is no value called linear for animation-direction.
The splits are not equal. That is, for some 10% gap it is rotating by 10 degree whereas for others it is rotating only by 5 degree. Make the splits equal.
The below snippet with all corrections done produces a smooth animation.
.bellImg {
height: 20px;
width: 20px;
position: absolute;
right: 10px;
top: 18px;
-webkit-animation-name: rotate;
animation-delay: 3s;
-webkit-animation-duration: 2s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: normal;
-webkit-transform-origin: 50% 0%;
-webkit-animation-timing-function: linear; /* or make your custom easing */
}
#-webkit-keyframes rotate {
0% {
-webkit-transform: rotate(0deg);
}
25% {
-webkit-transform: rotate(20deg);
}
75% {
-webkit-transform: rotate(-20deg);
}
100% {
-webkit-transform: rotate(0deg);
}
}
<img class="bellImg" src="https://cdn1.iconfinder.com/data/icons/freeline/32/bell_sound_notification_remind_reminder_ring_ringing_schedule-48.png">
Setting the animation's speed to depend on the position (that is, slow down as it reaches the extremes and quicken up in the middle) is impossible to achieve with pure CSS (even if we add extra elements).
For setting the animation's speed depending on its position, one option would be to do the following:
Add the image into a container element. Animate it such that it rotates from 20deg to -40deg.
Make the animation on the parent start earlier than the child by 1/3rd of the animation duration of both. That is, reduce the delay on parent by 0.66s. This is done to get the parent to offset initial rotation on the child. The difference is 1/3rd of animation duration because it is the time taken by parent to come to 0deg.
Change the keyframes for the image's animation such that the rotation is from -20deg to 40deg.
Set the animation-direction as alternate for both so that they go in forward direction for first iteration, in reverse for the next and so on.
Set the animation-timing-function as ease-in-out so that it slows down as it approaches the extremes. The effect is more apparent when the animation duration is increased.
.container {
position: absolute;
height: 20px;
width: 20px;
/* right: 10px; commented for demo */
top: 18px;
transform: rotate(20deg);
animation-name: rotate-container;
animation-delay: 2.33s;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-direction: alternate;
transform-origin: 50% 0%;
animation-timing-function: ease-in-out;
}
.bellImg {
height: 100%;
width: 100%;
transform: rotate(-20deg);
animation-name: rotate;
animation-delay: 3s;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-direction: alternate;
transform-origin: 50% 0%;
animation-timing-function: ease-in-out;
}
#keyframes rotate {
0% {
transform: rotate(-20deg);
}
100% {
transform: rotate(40deg);
}
}
#keyframes rotate-container {
0% {
transform: rotate(20deg);
}
100% {
transform: rotate(-40deg);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='container'>
<img class="bellImg" src="https://cdn1.iconfinder.com/data/icons/freeline/32/bell_sound_notification_remind_reminder_ring_ringing_schedule-48.png">
</div>
Prefix-free library is used in the snippet only to avoid browser prefixes.
The equation involved in the movement of a pendulum is a sinusoidal movement.
You can get this movement with the following animation
.base {
height: 600px;
width: 10px;
position: absolute;
animation: base 10s infinite linear;
background-color: lightgray;
transform: translateX(588px);
}
#keyframes base {
from {transform: translateX(77px);}
to {transform: translateX(760px);}
}
.element {
height: 10px;
width: 10px;
background-color: green;
border-radius: 100%;
animation: element 10s infinite;
transform: translateY(553px);
}
#keyframes element {
from {transform: translateY(294px); animation-timing-function: ease-out;}
25% {transform: translateY(36px); animation-timing-function: ease-in;}
50% {transform: translateY(294px); animation-timing-function: ease-out;}
75% {transform: translateY(553px); animation-timing-function: ease-in;}
to {transform: translateY(294px);}
}
.ref {
width: 800px;
height: 600px;
background-image: url(http://i.stack.imgur.com/Fx4bR.png);
background-size: cover;
}
<div class="base">
<div class="element">
</div>
</div>
<div class="ref"></div>
I had to use some hand-worked values to adjust for the background-image, but the key idea is in the timing functions.
If the preset function is not what you want, you can set a cubic bezier and adjust it as you want.
.base {
height: 600px;
width: 10px;
position: absolute;
animation: base 10s infinite linear;
background-color: lightgray;
transform: translateX(588px);
}
#keyframes base {
from {transform: translateX(77px);}
to {transform: translateX(760px);}
}
.element {
height: 10px;
width: 10px;
background-color: green;
border-radius: 100%;
animation: element 10s infinite;
transform: translateY(553px);
}
#keyframes element {
from {transform: translateY(294px);
animation-timing-function: cubic-bezier(0.1, 0.3, 0.3, 1);}
25% {transform: translateY(36px);
animation-timing-function: cubic-bezier(0.7, 0.0, 0.9, 0.7);}
50% {transform: translateY(294px);
animation-timing-function: cubic-bezier(0.1, 0.3, 0.3, 1);}
75% {transform: translateY(553px);
animation-timing-function: cubic-bezier(0.7, 0.0, 0.9, 0.7);}
to {transform: translateY(294px);}
}
.ref {
width: 800px;
height: 600px;
background-image: url(http://i.stack.imgur.com/Fx4bR.png);
background-size: cover;
}
<div class="base">
<div class="element">
</div>
</div>
<div class="ref"></div>
This is the image used for reference
And this would be the 2 timing functions applied to a pendulum
.test {
height: 400px;
width: 10px;
background-color: lightgreen;
display: inline-block;
margin: 10px 100px;
transform-origin: center top;
}
.anim1 {
animation: oscil1 6s infinite;
}
.anim2 {
animation: oscil2 6s infinite;
}
#keyframes oscil1 {
from {transform: rotate(0deg); animation-timing-function: cubic-bezier(0.1, 0.3, 0.3, 1);}
25% {transform: rotate(20deg); animation-timing-function: cubic-bezier(0.7, 0.0, 0.9, 0.7);}
50% {transform: rotate(0deg); animation-timing-function: cubic-bezier(0.1, 0.3, 0.3, 1);}
75% {transform: rotate(-20deg); animation-timing-function: cubic-bezier(0.7, 0.0, 0.9, 0.7);}
to {transform: rotate(0deg);}
}
#keyframes oscil2 {
from {transform: rotate(0deg); animation-timing-function: ease-out;}
25% {transform: rotate(20deg); animation-timing-function: ease-in;}
50% {transform: rotate(0deg); animation-timing-function: ease-out;}
75% {transform: rotate(-20deg); animation-timing-function: ease-in;}
to {transform: rotate(0deg);}
}
<div class="test anim1"></div>
<div class="test anim2"></div>
I haven't used CSS here, but since (it seems like) you just want to avoid libraries, I've implemented it in native JS. It uses the Math.sin() method to tween the values smoothly. As you can see, the effect is very smooth and requires very little code.
var img = document.querySelector( '.bellImg' ),
start = 0;
function sine(){
img.style.transform = "rotate(" + 20 * Math.sin( start ) + "deg)";
start += 0.05;
setTimeout(sine, 1000/30)
}
setTimeout( sine, 3000 );
.bellImg {
height: 20px;
width: 20px;
position: absolute;
left: 10px;
top: 18px;
}
<img class="bellImg" src="https://cdn1.iconfinder.com/data/icons/freeline/32/bell_sound_notification_remind_reminder_ring_ringing_schedule-48.png">
Hope this helps!
I have an image and want to move it to the right and then to left animation using CSS. However, I wanted to combine the drive with transform: scaleX (-1); as below:
----image---> move to right
move to left with transform: scaleX (-1)
<------image----
I have the code:
<div class="logo">
<img src="resources/images/logo.png" alt=""/>
</div>
.logo{
-webkit-animation-name: example; /* Chrome, Safari, Opera */
-webkit-animation-duration: 4s; /* Chrome, Safari, Opera */
-webkit-animation-delay: 1s; /* Chrome, Safari, Opera */
-webkit-animation-iteration-count: infinite ;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: linear;
animation-name: example;
animation-duration: 4s;
animation-delay: 1s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: linear;}
#-webkit-keyframes example {
from {
margin-left: -200px;
transform: scaleX(1);
}
to {
margin-left: 200px;
transform: scaleX(-1);
}}
#keyframes example {
from {
margin-left: -200px;
transform: scaleX(1);
}
to {
margin-left: 200px;
transform: scaleX(-1);
}}
You can not get this effect with an alternated animation, because the back movement is different from the forward movement.
First, we need to set a single animation for both directions; then , you can add keyframes to control the reversal
div {
width: 200px;
height: 200px;
background-color: coral;
animation: custom 4s infinite;
}
#keyframes custom {
0% {
margin-left: -200px;
transform: scaleX(1);
}
49% {
margin-left: 200px;
transform: scaleX(1);
}
50% {
margin-left: 200px;
transform: scaleX(-1);
}
100% {
margin-left: -200px;
transform: scaleX(-1);
}
}
<div>TEST</div>
I looking for changing my background-color after a css rotateY when my div is hover
#-webkit-keyframes spin {
0%{
-webkit-transform: rotateY(0deg); -webkit-transform-origin: 0% 0% 5;
}
100%{
-webkit-transform: rotateY(180deg); -webkit-transform-origin: 0% 0% 5;
}
}
.hex:hover{
background:red;
-webkit-animation-name: spin;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease-in-out;
-webkit-animation-duration: 1s;
}
You should define that in you keyframe as your element is animating on hover so you can change the background color in the animation keyframe itself.
Try this:
#-webkit-keyframes spin {
0%{
-webkit-transform: rotateY(0deg); -webkit-transform-origin: 0% 0% 5;
}
100%{
-webkit-transform: rotateY(180deg); -webkit-transform-origin: 0% 0% 5;
background:red;
}
}
.hex:hover{
-webkit-animation-name: spin;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease-in-out;
-webkit-animation-duration: 1s;
}
.hexHovered {
background:red;
}
To retain the backgroud color at hover you can use this javascript code.
$(".hex").hover(
function () { $(this).addClass(".hexHovered")
});
You can make the animation "persist" in time using animation-fill-mode.
Asuming that you want the color to persist, but not the rotation, it is alittle bit more complicated; you need two animations so that you can make only one persistent.
#-webkit-keyframes spin {
0% { -webkit-transform: rotateY(0deg); }
100%{ -webkit-transform: rotateY(180deg); }
}
#-webkit-keyframes red {
0% { background: white; }
100% { background: red; }
}
.hex {
-webkit-animation-fill-mode: none, forwards;
-webkit-animation-name: spin, red;
-webkit-animation-iteration-count: 0;
-webkit-animation-timing-function: ease-in-out;
-webkit-animation-duration: 1s, 0.1s;
-webkit-animation-delay: 0s 1s;
-webkit-transform-origin: 0% 0% 5;
}
.hex:hover{
-webkit-animation-iteration-count: 1;
}
fiddle
I would like to spin my div when I hover on it and as it spin I want to make it bigger like zoom in.
So far I have this:
[html]
div class="myMsg">
<p id="welly" style="color: #009">Welcome to Y3!<br><br><br>Thanks for stopping by!</p>
</div>
[css]
.myMsg {
background: white;
width: 800px;
height : 500px;
margin: 100px auto;
border: 1px solid black;
opactiy: 0.5;
-webkit-transform: rotate(360deg); /* Safari and Chrome */
-webkit-transform: scale(.1,.1) skew(45deg) translateX(-300px);
box-shadow: 0px 0px 200px grey;
}
.myMsg:hover {
opacity: 1;
-webkit-transform: rotate(360deg); /* Safari and Chrome */
-webkit-transform: scale(1,.1 skew(0deg);
box-shadow: 0px 0px 200px grey;
}
so I want it to spin before scaling to regular size
Any help is appreciated
First, to show that it can be done.
Now that that's out of the way, let's get down to the nitty gritty and show you how to do it.
First, you'll want to use animation to animate the properties and get the rotation effect. Sadly, a transition won't be enough since transitioning between 0 and 360 means you aren't going anywhere. So, animate your properties from one to the other on the hover. Your code will end up looking something like this:
#keyframes spin {
from { transform: scale(.1,.1) skew(0deg) rotate(0deg); }
to { transform: scale(1,1) skew(0deg) rotate(360deg); }
}
.myMsg:hover {
animation: spin 1s forwards;
}
The #keyframes defines the animation that will happen, and you want to transform from one set of properties to the final one. Then, you set your :hover to play that animation. The relevant properties for the animation are animation-name, animation-duration, and animation-fill-mode (which say that it should have the same properties as the last frame when it is done animating. Webkit requires prefixes, so you'll want to put those in too.
In addition to this, I also placed a transition: transform 1s; on the .myMsg class so that it would animate back after the mouse moves away. But do note that Webkit doesn't seem to play nice with the interaction between the two, so it is a bit choppy and less than ideal. But, with experimental properties like this, sometimes you get what you get.
Some side notes:
Your CSS isn't cross browser compatible, you should clean it up a bit
You're defining 1 transform property, and then immediately overriding it. All transforms need to go in the same declaration. They can't be combined like that
Define an infinite css animation with keyframes for spinning and switch to it on the hover. Use transition for the size (height/width) properties and change them on hover in css also.
Example: http://jsfiddle.net/6guCd/
div {
margin: 100px;
width: 100px;
height: 100px;
background: #f00;
-webkit-transition: all 200ms ease;
-moz-transition: all 200ms ease;
-ms-transition: all 200ms ease;
transition: all 200ms ease;
}
div:hover {
margin: 50px;
width: 200px;
height: 200px;
-webkit-animation-name: spin;
-webkit-animation-duration: 4000ms;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
-moz-animation-name: spin;
-moz-animation-duration: 4000ms;
-moz-animation-iteration-count: infinite;
-moz-animation-timing-function: linear;
-ms-animation-name: spin;
-ms-animation-duration: 4000ms;
-ms-animation-iteration-count: infinite;
-ms-animation-timing-function: linear;
animation-name: spin;
animation-duration: 4000ms;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
#-ms-keyframes spin {
from { -ms-transform: rotate(0deg); }
to { -ms-transform: rotate(360deg); }
}
#-moz-keyframes spin {
from { -moz-transform: rotate(0deg); }
to { -moz-transform: rotate(360deg); }
}
#-webkit-keyframes spin {
from { -webkit-transform: rotate(0deg); }
to { -webkit-transform: rotate(360deg); }
}
#keyframes spin {
from {
transform:rotate(0deg);
}
to {
transform:rotate(360deg);
}
}