I'm having a trouble with the effect I want to create. My body in the HTML file it's just a div with two images.
I was trying to give animation to the first image in the following way:
in 0% it starts at the beginning of the div (the fish's head is on the right)
in 100% it ends in the end, but at this point I want to rotate the image and keep that effect until it gets 0% again. (that is, the fish should point towards the left during the reverse motion)
But it just rotates in 100% and no more. I don't know if this happens because I don't understand some concept of the animation property.
This is all my code:
#keyframes fish01 {
0% {
left: 0%;
transform: rotateY(180deg);
}
1% {
transform: rotateY(0deg);
}
99% {
transform: rotateY(0deg);
}
100% {
left: 90%;
transform: rotateY(180deg);
}
}
body {
background-color: black;
}
div {
position: absolute;
margin-left: 18%;
margin-top: 3%;
width: 800px;
height: 500px;
border: 5px double #DDDDDD;
border-radius: 1em 1em;
background-image: url("https://i.onthe.io/vllkyt28101smv87bg.349283fe.jpg");
}
div img:nth-child(1) {
float: left;
position: absolute;
margin: 0px;
top: 20%;
width: 100px;
height: 50px;
transform: scale(1.5, 1.5);
animation-name: fish01;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: ease-in;
}
div img:nth-child(2) {
float: left;
position: absolute;
top: 20%;
left: 60%;
}
<section>
<div>
<img src="https://www.hyperone.com.eg/media/catalog/product/cache/4/thumbnail/9df78eab33525d08d6e5fb8d27136e95/f/i/fish_1.png" />
<img src="http://www.pets4homes.co.uk/images/fish_hero.png" />
</div>
</section>
I've tried everything in the #keyframes and looked into W3Schools website about animation property, but it didn't help me. Any suggestions?
Reason:
The behavior that is seen is expected one based on your #keyframes and the animation-direction setting. When the animation's direction is set to alternate, the UA executes the animation from 0 to 100 for the odd numbered iterations, 100 to 0 for the even numbered iterations.
As per your keyframes, the transform goes from rotateY(180deg) to rotateY(0deg) at 1% of the animation's duration itself and so during the odd numbered iterations you don't see any visible rotation (as duration is pretty small) and it goes from rotateY(180deg) (at 100%) to rotateY(0deg) (at 99%) because of which you don't get to see any visible rotation during even numbered iterations also.
The problem in writing keyframes for forward direction and re-using the same for the reverse (using animation-direction) is that it can be done only when the states are the same for both. In this case, it is not because the element should be in unrotated state during forward movement and should have rotateY(180deg) during the reverse movement.
Solution:
For the element to be seen in its rotated state, the transform must be retained for some time. So, for your case it is better to do away with the animation-direction: alternate setting and write both the forward and reverse motions within the keyframes itself like in the below snippet.
(Note: Since we are writing both forward and reverse motions within the keyframes, you may have to double the animation-duration).
#keyframes fish01 {
0% {
left: 0%;
transform: rotateY(0deg);
}
49.5% {
left: 90%;
transform: rotateY(0deg);
}
50.5% {
left: 90%;
transform: rotateY(180deg);
}
100% {
left: 0%;
transform: rotateY(180deg);
}
}
body {
background-color: black;
}
div {
position: absolute;
margin-left: 18%;
margin-top: 3%;
width: 800px;
height: 500px;
border: 5px double #DDDDDD;
border-radius: 1em 1em;
background-image: url("https://i.onthe.io/vllkyt28101smv87bg.349283fe.jpg");
}
div img:nth-child(1) {
float: left;
position: absolute;
margin: 0px;
top: 20%;
width: 100px;
height: 50px;
transform: scale(1.5, 1.5);
animation-name: fish01;
animation-duration: 10s; /* double of original time */
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-timing-function: ease-in;
}
div img:nth-child(2) {
float: left;
position: absolute;
top: 20%;
left: 60%;
}
<section>
<div>
<img src="https://www.hyperone.com.eg/media/catalog/product/cache/4/thumbnail/9df78eab33525d08d6e5fb8d27136e95/f/i/fish_1.png" />
<img src="http://www.pets4homes.co.uk/images/fish_hero.png" />
</div>
</section>
The problem was that you had animation-direction: alternate; in your CSS. To compensate for removing this, you also need to make the img moving to left: 90% being at the 50% mark in the animation, not the 100% mark.
Hope this helps! :)
#keyframes fish01{
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);
}
}
body {
background-color: black;
}
div {
position: absolute;
margin-left: 18%;
margin-top: 3%;
width: 800px;
height: 500px;
border: 5px double #DDDDDD;
border-radius: 1em 1em;
background-image: url("https://i.onthe.io/vllkyt28101smv87bg.349283fe.jpg");
}
div img:nth-child(1) {
float: left;
position: absolute;
margin: 0px;
top: 20%;
width: 100px;
height: 50px;
transform: scale(1.5, 1.5);
animation-name: fish01;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-timing-function: ease-in;
}
div img:nth-child(2) {
float: left;
position: absolute;
top: 20%;
left: 60%;
}
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8"/>
<title>CSS rotate animation</title>
<link rel="stylesheet" href="Transicion02.css"/>
</head>
<body>
<section>
<div>
<img src="https://www.hyperone.com.eg/media/catalog/product/cache/4/thumbnail/9df78eab33525d08d6e5fb8d27136e95/f/i/fish_1.png"/>
<img src="http://www.pets4homes.co.uk/images/fish_hero.png"/>
</div>
</section>
</body>
</html>
Related
Please help, when I'm trying to play animation with moving ball in position X and Y at the same time it doesn't work, some strange behaviour. I would like to look like a batted and falling ball
.ball {
position: absolute;
left: 18%;
bottom: 100px;
width: 40px;
height: 40px;
background-color: cadetblue;
border-radius: 50%;
animation: fly-ball-x 2s, fly-ball-y 2s;
}
#keyframes fly-ball-x {
100% {
transform: translateX(300px);
}
}
#keyframes fly-ball-y {
100% {
transform: translateY(100px);
}
}
<div class="ball"></div>
**The result I'm expecting is like the code below:**
#keyframes fly-ball-x {
100% {
left: 300px;
}
}
#keyframes fly-ball-y {
100% {
bottom: 0;
}
}
.ball {
position: absolute;
left: 18%;
bottom: 100px;
width: 40px;
height: 40px;
background-color: cadetblue;
border-radius: 50%;
animation: fly-ball-x 2s cubic-bezier(0.17, 0.67, 0.6, 1), fly-
ball-y 2s;
}
<div class="ball"></div>
.ball {
position: absolute;
left: 18%;
bottom: 100px;
width: 40px;
height: 40px;
background-color: cadetblue;
border-radius: 50%;
animation: fly-ball 2s
}
#keyframes fly-ball {
100% {
transform: translateX(300px) translateY(100px);
}
}
<div class="ball"></div>
It is because you weren't running the animations concurrently. Here both translations are just being run at the same time. You just had a bit more than you needed.
EDIT
Check out this blog post. It gives explanations on the kinds of curves it seems you are going for Curved Path Animations In CSS
I have 2 images with transparent background and need to put one on top of each other with the same positioning:
1 spinning (underneath)
1 fixed (above)
I need to have the whole image composition to be centered and to have its size adjusted depending on the window size.
I used an ::after pseudo element for the fixed one but couldn’t get its position and size to follow the spinning one.
I suppose the background-size property should be involved but didn’t manage to use it properly.
Would appreciate any advice, even if it involves going with a totally different approach than the ::after pseudo class.
Many thanks.
body{
width: 100%;
height: 100%;
background-color: #000;
text-align: center;
color: #fff;
}
.main-container{
background-color: #00f;
width: 50%;
margin: 0 auto;
}
.engine-container{
}
.engine-complete{
position: relative;
width: 100%;
height: auto;
margin: 0 auto;
}
.engine-complete::after{
content: "";
position: absolute;
width: 191px;
height: 192px;
top: 1px;
left: 0;
background-image: url(https://image.ibb.co/jOqNma/engine1_crpd.png);
}
.engine-rotating{
width: 50%;
height: auto;
}
.spin {
animation-duration: 15s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function:linear;
animation-play-state: running;
}
#keyframes spin {
from {
transform:rotate(360deg);
}
to {
transform:rotate(0deg);
}
}
<div class="main-container">
<h1>spinning engine</h1>
<div class="engine-container">
<div class="engine-complete">
<img src="https://image.ibb.co/nwOKXF/engine1.png" width=191 height=192 class="engine-rotating spin"/>
</div>
</div>
</div>
Something like this?
EDIT: Instead of setting the image as a background using the ::after pseudo-class, I added the fixed image into the html. I also eliminated one of your containers.
I centred the animated image using text-align:center and centred the fixed image using position: absolute
I set both images to 30% width relative their parent .engine-container
The fixed image has a higher z-index than the animated image so that it always appears over it. The images also change size accordingly, relative to window size.
body {
width: 100%;
height: 100%;
background-color: #000;
text-align: center;
color: #fff;
}
.main-container {
background-color: #00f;
width: 50%;
margin: 0 auto;
}
.engine-container {
text-align: center;
position: relative;
}
.engine-rotating,
.engine-fixed {
width: 30%;
}
.engine-fixed {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(0deg);
z-index: 5000;
}
.spin {
animation-duration: 15s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-play-state: running;
}
#keyframes spin {
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
<div class="main-container">
<h1>spinning engine</h1>
<div class="engine-container">
<img src="https://image.ibb.co/nwOKXF/engine1.png" class="engine-rotating spin" />
<img src="https://image.ibb.co/jOqNma/engine1_crpd.png" class="engine-fixed" alt="">
</div>
</div>
UPDATE
Heres what I came up with:
A similar effect using ::after. I was able to achieve this by inserting the image url into the content: rule, rather than setting a background image.
body {
width: 100%;
height: 100%;
background-color: #000;
text-align: center;
color: #fff;
}
.main-container {
background-color: #00f;
width: 50%;
margin: 0 auto;
}
.engine-container{
text-align: center;
position: relative;
}
.engine-rotating{
}
.engine-container::after{
content: url('https://image.ibb.co/jOqNma/engine1_crpd.png');
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(0deg);
z-index: 5000;
}
.spin{
animation-duration: 15s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-play-state: running;
}
#keyframes spin{
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
<div class="main-container">
<h1>spinning engine</h1>
<div class="engine-container">
<img src="https://image.ibb.co/nwOKXF/engine1.png" class="engine-rotating spin" />
</div>
</div>
Set position for .engine-complete::after to relative
.engine-complete::after {position: relative}
body{
width: 100%;
height: 100%;
background-color: #000;
text-align: center;
color: #fff;
}
.main-container{
background-color: #00f;
width: 50%;
margin: 0 auto;
}
.engine-container{
}
.engine-complete{
position: relative;
width: 100%;
height: auto;
margin: 0 auto;
}
.engine-complete::after{
content: "";
position: relative; /* this was changed */
width: 191px;
height: 192px;
top: 1px;
left: 0;
background-image: url(https://image.ibb.co/jOqNma/engine1_crpd.png);
}
.engine-rotating{
width: 50%;
height: auto;
}
.spin {
animation-duration: 15s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function:linear;
animation-play-state: running;
}
#keyframes spin {
from {
transform:rotate(360deg);
}
to {
transform:rotate(0deg);
}
}
<div class="main-container">
<h1>spinning engine</h1>
<div class="engine-container">
<div class="engine-complete">
<img src="https://image.ibb.co/nwOKXF/engine1.png" width=191 height=192 class="engine-rotating spin"/>
</div>
</div>
</div>
I am trying to build a simple CSS3 animation, a pulsing square inside a bigger square (centered).
It seems to work fine except on IE, at the end of the animation the inner square move to up-left of his parent.
I didn't find a solution, help me please. What am I doing wrong?
#foo{
position: relative;
display: table;
margin: auto;
width: 100px;
height: 100px;
top: 50px;
background: #ccf;
}
#foo::before{
content:"";
position: absolute;
display: inline-block;
width: 50%;
height: 50%;
left: 50%;
top: 50%;
background: #55a;
animation: 1s ease-in-out infinite pulse;
}
#keyframes pulse {
0% { transform: translate(-50%, -50%) scale(.2,.2); }
50% { transform: translate(-50%, -50%) scale(.8,.8); }
100% { transform: translate(-50%, -50%) scale(.2,.2); }
}
Here a JsFiddle of the code
How strange. It looks like IE and Edge are having some issue resetting the transforms on subsequent loops.
Although I couldn't find a direct solution to the browser's rendering problem (likely a bug), your sample looks like a great place to use the absolute centering trick. By not having the extra translate to center it, it works in IE, and is a bit simpler.
Working Example (jsFiddle):
#foo{
position: relative;
display: table;
margin: auto;
width: 100px;
height: 100px;
top: 50px;
background: #ccf;
}
#foo::before{
content:"";
position: absolute;
display: inline-block;
width: 50%;
height: 50%;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
background: #55a;
animation: 1s ease-in-out infinite pulse;
}
#keyframes pulse {
0% {transform: scale(.2,.2); }
50% {transform: scale(.8,.8); }
100% {transform: scale(.2,.2); }
}
<i id="foo"/>
The problem is that the transform property's value has multiple part like translate, scale etc.
This is a theoretical question about element, let's .loader that has transform:translate(10px, 10px) and in the animation I want to animate the scale property. In this case, the browser will not take the transform:translate(10px, 10px) and will take only the scale.
I am looking for a way around this problem.
Here is an example to this question. Please, keep attention that I'm not looking for an answer to this particular example (like: wrap the element or add the translate value to the animation definition) but a generic solution (if exist, of course).
.loading {
position: relative;
width: 100px;
height: 100px;
background: #eee;
}
.loading:before,
.loading:after {
content: "";
width: 50%;
height: 50%;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
background-color: #fff;
opacity: 0.6;
position: absolute;
top: 0;
left: 0;
/* the broswer doesn't take this */
transform: translate(100px, 300px);
-webkit-animation: bounce 2s infinite ease-in-out;
animation: bounce 2s infinite ease-in-out;
}
.loading:after {
-webkit-animation-delay: -1s;
animation-delay: -1s;
}
#keyframes bounce {
0%, 100% {
transform: scale(0);
-webkit-transform: scale(0);
}
50% {
transform: scale(1);
-webkit-transform: scale(1);
}
}
<div class="loading"></div>
Generally when you add an animation with changes to the transform property then the transforms that are specified in the base element should also be carried over to be present within the animation's keyframes also. That is, the new transforms (that are part of the animation) should be added over on top of the existing transform and not overwrite it. Below is how it should be done.
.loading {
position: relative;
width: 200px;
height: 200px;
background: #eee;
}
.loading:before,
.loading:after {
content: "";
width: 50%;
height: 50%;
border-radius: 50%;
background-color: #fff;
opacity: 0.6;
position: absolute;
top: 0;
left: 0;
transform: translate(100px, 300px);
animation: bounce 2s infinite ease-in-out;
}
.loading:after {
animation-delay: -1s;
}
#keyframes bounce {
0%, 100% {
transform: scale(0) translate(100px, 300px);
}
50% {
transform: scale(1) translate(100px, 300px);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="loading"></div>
I wrote a similar answer here to a question about adding multiple animations on an element with each of those animations modifying the transform property's values independent of the other. I am linking it here only for reference and don't think they are duplicates.
Having said the above, adding the the original transform to each animation's kefyrames is not possible when you are trying to create animation libraries or trying to split each animation into a separate class. Say for example, you want to add the same bounce animation to multiple elements and each of them have a different initial transform setting then it becomes impossible to add it to animation's keyframe.
In such cases, you can still achieve the desired output using CSS but it would be very difficult (almost impossible in my opinion) to get it done with a single element.
What options do you have? Well, one option is for you to add the animation on a wrapper element.
.loading-wrapper {
position: relative;
width: 200px;
height: 200px;
background: #eee;
}
.loading-before, .loading-after {
position: absolute;
width: 50%;
height: 50%;
top: 0px;
left: 0px;
animation: bounce 2s infinite ease-in-out;
}
.loading-before:before,.loading-after:before {
content: "";
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #fff;
opacity: 0.6;
position: absolute;
top: 0;
left: 0;
transform: translate(100px, 300px);
}
.loading-after {
animation-delay: -1s;
}
#keyframes bounce {
0%, 100% {
transform: scale(0);
}
50% {
transform: scale(1);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="loading-wrapper">
<div class="loading-before"></div>
<div class="loading-after"></div>
</div>
The solution is quite generic and you can apply it to almost all such cases. The drawback is that if you want to stack multiple such transformations then you'd likely end up with multiple such wrappers. There is no pure CSS way other than adding original transformations within the animation's keyframes also.
The below snippet is another sample.
.move-n-scale {
position: relative;
height: 100px;
width: 100px;
background: sandybrown;
border: 1px solid chocolate;
transform: scale(0.5);
animation: move 1s linear infinite alternate-reverse;
}
.move {
position: relative;
display: inline-block;
animation: move-only 1s linear infinite alternate-reverse;
}
.scale {
position: absolute;
height: 100px;
width: 100px;
top: 0px;
left: 0px;
background: sandybrown;
border: 1px solid chocolate;
transform: scale(0.5);
}
#keyframes move {
from {
transform: translateX(0px) scale(0.5);
}
to {
transform: translateX(300px) scale(0.5);
}
}
#keyframes move-only {
from {
transform: translateX(0px);
}
to {
transform: translateX(300px);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='move-n-scale'></div>
<div class='move'>
<div class='scale'></div>
</div>
Note: Just to clarify, I did notice that you had mentioned about not wanting a solution which is very specific to this problem like wrap it etc. But, I had still added this solution as an answer because it is the only generic solution which I am aware of. I had added the second snippet only to show that is is indeed generic.
You can delete the translate(100px, 300px); in .loading:after, then set the translate(100px, 300px) in #keyframes, like follows:
#keyframes bounce {
0%,
100% {
transform: scale(0)translate(100px, 300px);
-webkit-transform: scale(0)translate(100px, 300px);
}
50% {
transform: scale(1)translate(100px, 300px);
;
-webkit-transform: scale(1)translate(100px, 300px);
}
}
I made a animation and here is the demo.
But the contents won't animate with the div together, any suggestions?
HTML
<div id="fdiv" align="center">
<h1>Hello!</h1>
<h1>Hello!</h1>
<h1>Hello!</h1>
<h1>Hello!</h1>
<h1>Hello!</h1>
<h1>Hello!</h1>
</div>
CSS
#fdiv{
width: 10px;
height: 10px;
position: absolute;
margin-left: -5px;
margin-top: -5px;
left: 50%;
top: 50%;
background-color: red;
}
.go{
-webkit-animation: spinAndZoom 1s 1;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes spinAndZoom {
0% {
width: 10px;
height: 10px;
margin-left: -5px;
margin-top: -5px;
-webkit-transform: rotateZ(0deg);
}
100% {
width: 400px;
height: 400px;
margin-left: -200px;
margin-top: -200px;
-webkit-transform: rotateZ(360deg);
}
}
JS
$(function(){
$("#fdiv").delay(1000).addClass("go");
});
With not animating you mean the size of the content? Then add font-size to your animation.
#-webkit-keyframes spinAndZoom {
0% {
width: 10px;
height: 10px;
margin-left: -5px;
margin-top: -5px;
-webkit-transform: rotateZ(0deg);
font-size: 0;
}
100% {
width: 400px;
height: 400px;
margin-left: -200px;
margin-top: -200px;
-webkit-transform: rotateZ(360deg);
font-size: 16px;
}
}
As shennan mentioned, the animation of font-size is most of the time a bit jerky.
I've added ease-in to the animation, to make it appear less jerky at the end.
.go {
-webkit-animation: spinAndZoom 1s 1 ease-in;
-webkit-animation-fill-mode: forwards;
}
Updated Fiddle
You can go with Kilian's suggestion by adding font-size to the webkit animation, but the results are a little jerky.
I would either use a dynamically created image/canvas to create the text, or simply call your losses and add overflow:hidden to the #fdiv CSS block to get rid of the initial text spilling over the edge of your div:
#fdiv{
width: 10px;
height: 10px;
position: absolute;
margin-left: -5px;
margin-top: -5px;
left: 50%;
top: 50%;
background-color: red;
overflow:hidden; /* here is your eureka fix */
}