CSS3 animation bug in IE - css

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"/>

Related

Trying to fill an image with color and making it go down with css

I'm trying to fill this nos bottle then slowly empty it up with css so first the "fill" goes up then slowly slowly drains down, I tried but came with a very terrible result
#bottle, #fill {
position: fixed;
top: 50%;
left: 50%;
}
.box {
width: 96px;
height: 195px;
border-radius: 10px;
text-align: center;
color: #ddd;
font-size: 25px;
font-weight: 600;
position: relative;
overflow: hidden;
top: 50%;
left: 50%;
}
.box:before {
content: "";
position: absolute;
width: 400px;
height: 400px;
background: #00acee;
left: 50%;
transform: translateX(-50%);
border-radius: 40%;
animation: fill 1s cubic-bezier(0, 1.62, 0.27, -0.67) infinite;
z-index: -1;
}
#keyframes fill {
from {
top: 250px;
transform: translateX(-50%) rotate(0deg);
}
to {
top: -50px;
transform: translateX(-50%) rotate(360deg);
}
}
<div class="box">
<img id="bottle" src="https://cdn.discordapp.com/attachments/350561379234873354/813833593084313650/bottle.png" width=100 height=200>
</div>
If anyone could point how can i achieve this would be awesome.
You can try something like that, but you should consider just left backgroung transparent inside bottom image, outside put a solid color, like black.
#bottle, #fill {
top: 50%;
left: 50%;
}
.box {
width: 96px;
height: 195px;
border-radius: 10px;
text-align: center;
color: #ddd;
font-size: 25px;
font-weight: 600;
position: relative;
overflow: hidden;
top: 50%;
left: 50%;
}
.box:before {
content: "";
position: absolute;
width: 400px;
height: 400px;
background: #00acee;
left: 50%;
transform: translateX(-50%);
border-radius: 40%;
animation: fill 7s cubic-bezier(1, 2.7, 1, -1.7) infinite;
z-index: -1;
}
#keyframes fill {
from {
top: 450px;
transform: translateX(-50%) rotate(0deg);
}
to {
top: -50px;
transform: translateX(-50%) rotate(360deg);
}
}
<div class="box">
<img id="bottle" src="https://cdn.discordapp.com/attachments/350561379234873354/813833593084313650/bottle.png" width=100 height=200>
</div>
I'm not absolutely sure what effect you want, but one thing to notice is that you can have the filling and the emptying all in the same animation, without necessarily needing to involve a cubic Bezier function, which in this case seemed to partly fill the bottle, then empty then partly fill but to a different level.
Simplifying things but introducing more detail into the keyframes here's an example of the bottle filling much faster than it empties, by having the percentage of the animation used for filling as much smaller than the emptying.
There are of course many variations on this which can be achieved by having the percentages differ. Also you could reintroduce a cubic Bezier to make the movement less uniform, but that's for your experimentation as I don't know exactly what final effect is wanted.
<head>
<style>
#bottle, #fill {
/* position: fixed; NOTE. had to change this position fixed to absolute get it to line up on Stack Overflow. Outside SO it was fine as fixed */
position: absolute;
top: 50%;
transform: translateY(-50%);
left: calc(50% - 50px);
}
.box {
width: 96px;
height: 195px;
border-radius: 10px;
text-align: center;
color: #ddd;
font-size: 25px;
font-weight: 600;
position: relative;
overflow: hidden;
top: 50%;
left: 50%;
}
.box:before {
content: "";
position: absolute;
width: 400px;
height: 400px;
background: #00acee;
left: 50%;
transform: translateX(-50%);
border-radius: 40%;
/* animation: fill 20s cubic-bezier(0, 1.62, 0.27, -0.67) infinite; */
animation: fill 20s linear infinite;
z-index: -1;
animation-fill-mode: forwards; /* added */
}
#keyframes fill {
0% {
top: 250px;
transform: translateX(-50%) rotate(0deg);
}
10% {
top: -50px;
top: 75px;
transform: translateX(-50%) rotate(360deg);
}
20% {
top: 75px;
transform: translateX(-50%) rotate(0deg);
}
22% {
top: 75px;
transform: translateX(-50%) rotate(0deg);
}
80% {
transform: translateX(-50%) rotate(360deg);
}
100% {
top: 250px;
transform: translateX(-50%) rotate(0deg);
}
}
</style>
</head>
<body>
<div class="box">
<img id="bottle" src="https://cdn.discordapp.com/attachments/350561379234873354/813833593084313650/bottle.png" width=100 height=200>
</div>
</body>
Note: in the SO snippet system the position fixed had the effect of separating the blob (liquid) from the bottle - it was fine when the code was just run as it was outside the SO system. To demo it here I have made the bottle position absolute and centered the bottle and blob, just so you can get an idea while here. You can remove the absolute and go back to fixed outside SO.

How can i move images up to down using keyframe

I want my image to start with top:0 and ends with bottom:0 with smooth animation. I am struggling to find out the solution.
To be very clear i cannot use background images for SEO purpose. JS solutions are also welcome.
.element {
height: 200px;
width: 400px;
background-color: red;
position: relative;
margin: auto;
overflow: hidden;
}
.element img {
animation: nudge 5s linear infinite alternate;
position: absolute;
top: 0;
left: 0;
}
#keyframes nudge {
0%, 100% {
top: 0;
bottom: auto;
}
50% {
bottom: 0%;
top: auto;
}
}
<div class="element">
<img src="https://www.neelnetworks.com/wp-content/uploads/2018/08/ecommerce-bg.png" alt=""></div>
Instead of trying to animate on top and bottom, you can animate on translateY and move it down with top so it doesnt go off screen
.element {
height: 200px;
width: 400px;
background-color: red;
position: relative;
margin: auto;
overflow: hidden;
}
.element img {
animation: nudge 2s linear infinite alternate;
position: absolute;
top: 0;
transform: translateY(0);
}
#keyframes nudge {
100% {
transform: translateY(-100%);
top: 100%;
}
}
<div class="element"><img src="https://www.neelnetworks.com/wp-content/uploads/2018/08/ecommerce-bg.png" alt=""></div>

CSS animation for moving div to top and then to center

I am trying to make a CSS animation (i can't use javascript) with these steps:
Have a div of which you can't know in advance its position or size (in the fiddle i have set the size for testing)
The div gets resized (width 100% height 50 pixels) and moves to the top of the page while its content disappears
The div turns into a circle and moves to the center of the page
This is what i have attempted so far:
https://jsfiddle.net/v3bt1mar/5/
.turning {
width: 80%;
height: 120px;
background-color: #00FF00;
}
.turning:active {
background: red;
animation: 10.5s;
display: block !important;
position: fixed;
content: "";
overflow: hidden;
animation: resizeList 10.5s forwards;
}
.turning:active * {
animation: fadeContent 1s forwards;
}
#keyframes fadeContent {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 0;
}
}
#keyframes resizeList {
25% {
width: 100%;
height: 50px;
top: 10px;
left: 0%;
// transform: translate(0%, 0%) rotateY(0deg);
border-radius: 0%;
}
100% {
border-radius: 50%;
top: calc(50% - 50px);
left: calc(50% - 50px)";
// transform: translate(~"calc(50vw - 50px)", ~"calc(50vh - 50px)") rotateY(180deg);
transform: rotateY(180deg);
width: 100px;
height: 100px;
}
}
But it's still far from what i am expecting.
On Mozilla it doesn't move vertically, on Chrome it does move but not smoothly (just at every keyframe, apparently)
Then i don't know why it moves back to the left rather than to the center of the page
On top of that it works differently on Mozilla and Chrome (on Mozilla it doesn't move to the top, on Chrome it does but not smoothly)
If you add position:absolute; to .turning and remove the rotate transformation in the keyframe, the animation does what you are describing: https://jsfiddle.net/v3bt1mar/7/
Change:
100% {
border-radius: 50%;
top: calc(50% - 50px);
left: calc(50% - 50px)";
// transform: translate(~"calc(50vw - 50px)", ~"calc(50vh - 50px)") rotateY(180deg);
transform: rotateY(180deg);
width: 100px;
height: 100px;
}
To:
100% {
border-radius: 50%;
top: calc(50% - 50px);
left: 50%;
// transform: translate(~"calc(50vw - 50px)", ~"calc(50vh - 50px)") rotateY(180deg);
transform: rotateY(180deg);
width: 100px;
height: 100px;
}
This will keep image at center. Also try adding keyframes for 50% and 75% transition. That should smooth out the transition a bit.
The actual issue was that it was copied from a less file and it contained single line comments which are not allowed into normal CSS. On top of that i had left calc as a string so that LESS won't sum the values while parsing
With a few adjustments taken from the other answers i managed to fix the animation the way i wanted (the rotate was intended, i just didn't think it was worth mentioning)
https://jsfiddle.net/v3bt1mar/12/
.turning {
width: 80%;
height: 120px;
background-color: #00FF00;
}
.turning:active {
background: red;
display: block !important;
position:fixed;
overflow: hidden;
animation: resizeList 1s forwards;
top:calc(50% - 50px);
left: 0;
}
.turning:active * {
animation: fadeContent 1s forwards;
}
#keyframes fadeContent {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 0;
}
}
#keyframes resizeList {
25% {
width: 100%;
height: 50px;
top: 10px;
left: 0%;
border-radius: 0%;
transform: rotateY(0deg);
}
100% {
border-radius: 50%;
top: calc(50% - 50px);
left: calc(50% - 50px);
transform: rotateY(180deg);
width: 100px;
height: 100px;
}
}

How keep the image rotated during the reverse movement?

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>

CSS transition between left -> right and top -> bottom positions

Is it possible to use CSS transitions to animate something between a position set as left: 0px to right: 0px so it goes all the way across the screen? I need to accomplish the same thing with top to bottom. Am I stuck calculating the screen width / object-size?
#nav {
position: absolute;
top: 0px;
left: 0px;
width: 50px;
height: 50px;
-webkit-transition: all 0.5s ease-out;
}
.moveto {
top: 0px;
right: 0px;
}
and then I use jQuery's .addClass
You can animate the position (top, bottom, left, right) and then subtract the element's width or height through a CSS transformation.
Consider:
$('.animate').on('click', function(){
$(this).toggleClass("move");
})
.animate {
height: 100px;
width: 100px;
background-color: #c00;
transition: all 1s ease;
position: absolute;
cursor: pointer;
font: 13px/100px sans-serif;
color: white;
text-align: center;
}
/* ↓ just to position things */
.animate.left { left: 0; top: 50%; margin-top: -100px;}
.animate.right { right: 0; top: 50%; }
.animate.top { top: 0; left: 50%; }
.animate.bottom { bottom: 0; left: 50%; margin-left: -100px;}
.animate.left.move {
left: 100%;
transform: translate(-100%, 0);
}
.animate.right.move {
right: 100%;
transform: translate(100%, 0);
}
.animate.top.move {
top: 100%;
transform: translate(0, -100%);
}
.animate.bottom.move {
bottom: 100%;
transform: translate(0, 100%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Click to animate
<div class="animate left">left</div>
<div class="animate top">top</div>
<div class="animate bottom">bottom</div>
<div class="animate right">right</div>
And then animate depending on the position...
For elements with dynamic width it's possible to use transform: translateX(-100%); to counter the horizontal percentage value. This leads to two possible solutions:
1. Option: moving the element in the entire viewport:
Transition from:
transform: translateX(0);
to
transform: translateX(calc(100vw - 100%));
#viewportPendulum {
position: fixed;
left: 0;
top: 0;
animation: 2s ease-in-out infinite alternate swingViewport;
/* just for styling purposes */
background: #c70039;
padding: 1rem;
color: #fff;
font-family: sans-serif;
}
#keyframes swingViewport {
from {
transform: translateX(0);
}
to {
transform: translateX(calc(100vw - 100%));
}
}
<div id="viewportPendulum">Viewport</div>
2. Option: moving the element in the parent container:
Transition from:
transform: translateX(0);
left: 0;
to
left: 100%;
transform: translateX(-100%);
#parentPendulum {
position: relative;
display: inline-block;
animation: 2s ease-in-out infinite alternate swingParent;
/* just for styling purposes */
background: #c70039;
padding: 1rem;
color: #fff;
font-family: sans-serif;
}
#keyframes swingParent {
from {
transform: translateX(0);
left: 0;
}
to {
left: 100%;
transform: translateX(-100%);
}
}
.wrapper {
padding: 2rem 0;
margin: 2rem 15%;
background: #eee;
}
<div class="wrapper">
<div id="parentPendulum">Parent</div>
</div>
Demo on Codepen
Note: This approach can easily be extended to work for vertical positioning. Visit example here.
This worked for me on Chromium. The % for translate is in reference to the size of the bounding box of the element it is applied to so it perfectly gets the element to the lower right edge while not having to switch which property is used to specify it's location.
topleft {
top: 0%;
left: 0%;
}
bottomright {
top: 100%;
left: 100%;
-webkit-transform: translate(-100%,-100%);
}
In more modern browsers (including IE 10+) you can now use calc():
.moveto {
top: 0px;
left: calc(100% - 50px);
}

Resources