Delay after each CSS translateX animation - css

I'm using CSS transform translateX to move a Gif from left to right. The gif stops and belches towards the end of the Gif animation but the Gif is still being translated along the X co-ordinate, so it doesn't look good!
How can I add a pause/delay at the end of the translateX.
There's a similar question on Stackoverflow regarding a Rotate, and the answer is the following code:
66%, 100% {
transform:rotatey(0deg);
}
But for the life of me I can't figure out how to apply to mine.
.gif-image {
width: 30%;
animation-name: slideLeftToRight;
animation-duration: 20s;
animation-iteration-count: infinite;
}
#keyframes slideLeftToRight {
from {transform: translateX(0px)}
to {transform: translateX(400px)}
}
body{
background-color: #6dba94;
}
<div class="container">
<img class="gif-image" src="https://cdn.dribbble.com/users/672882/screenshots/1972683/character-rig-800x600.gif" />
</div>

This is an interesting one since you can't use a transition delay quite the same as in most circumstances since the GIF never stops. So your case basically boils down to timing up the animation to match with the GIF timing. This is going to be hard to do, especially if you didn't make the GIF yourself. (If you did, maybe it'd be easier for you to tell exactly when the guy starts and stops walking, in milliseconds.)
That said, hard does not mean impossible.
Important note before we start: The GIF is gonna keep playing over and over, even if you update your code in JS Fiddle or CodePen or a Stack Snippet or what have you. So you can end up thinking your animation timing is all off when it's actually not. In testing this, I copied the URL I was working from in CodePen and then kept closing the tab, reopening a new one, and pasting the URL into there to reload it with the GIF starting from its beginning. This is tedious, but I don't know a better way.
Anyway...
First you gotta figure out how long the GIF lasts because it'll make our life a million times easier to base the animation duration around the GIF's duration. I was guessing initially that it'd be a nice round number like exactly 5 seconds, but in testing it seemed to get off after a few iterations, like it was actually slightly longer. I'm ballparking it at 5.15 seconds.
So let's make our guy walk to the right when he's done belching. First we gotta figure out how long exactly he takes before he starts walking. (If you know this number exactly, your life will be way easier. I had to use guess and check.)
With some testing, I figured out he starts walking approximately 42% of the way into the GIF, or about 2163ms into it, if the GIF is 5.15 seconds long (5150ms). So we don't start our translation until that point:
#keyframes animationName {
0% {
transform: translateX(0px);
}
42% {
transform: translateX(0px);
}
100% {
transform: translateX(200px);
}
}
That basically gives us this:
.gif-image {
width: 250px;
animation-iteration-count: infinite;
animation-name: slideLeftToRightRepeating;
animation-duration: 5.15s;
}
#keyframes slideLeftToRightRepeating {
0% {
transform: translateX(0px);
}
42% {
transform: translateX(0px);
}
100% {
transform: translateX(200px);
}
}
body {
background-color: #6dba94;
}
<div class="container">
<div><img class="gif-image" src="https://cdn.dribbble.com/users/672882/screenshots/1972683/character-rig-800x600.gif" /></div>
</div>
Once we get that part down, if you want him to keep walking sideways like you have in your question with a long animation duration, it's just a matter of multiplying our animation duration by however many times you want to repeat the motion, and then dividing our percentages by that same amount.
So let's say you want to have him repeat the animation five times. Our animation duration now becomes (5 * 5.15s) = 20.75s.
Then, in our percentages, every 20% of the animation (because we're dividing it in fifths) will be a repeat of the pattern we established above. So at the 20% mark, we have the same effect as at the 100% mark above.
We figured out he starts walking around 42% of the way through, so we take 42% of 20% to get 8.4%. Our keyframes now look like this:
#keyframes animationName {
0% {
transform: translateX(0px);
}
8.4% {
transform: translateX(0px);
}
20% {
transform: translateX(200px);
}
28.4% {
transform: translateX(200px);
}
40% {
transform: translateX(400px);
}
.....
}
In practice, this proved to be not quite right (I guess my 42% estimation isn't perfect). Revising our numbers a bit, I came up with 0%, 11.5%, 20%, 31.5%, etc.
At the end, we have 100% { transform: translateX(1000px); }. That's a 200px translation five times.
Here's a pretty good starting spot where things go decently well, but the timing isn't exact. I'll leave it up to you to mess with it to get the numbers exactly right and also to adjust the distance he walks each time to fit your circumstance. Hopefully this helps.
Note that I think your life will be easier if you set the width of the GIF as well as the translation distance in fixed units, otherwise you may find that with relative units like percentages that your guy appears to either be walking in place or taking huge bounds across the screen depending how wide it is.
.gif-image {
width: 250px;
animation-iteration-count: infinite;
animation-duration: 20.75s;
animation-name: slideLeftToRightSlowly;
}
#keyframes slideLeftToRightRepeating {
0% {
transform: translateX(0x);
}
42% {
transform: translateX(0px);
}
100% {
transform: translateX(200px);
}
}
#keyframes slideLeftToRightSlowly {
0% {
transform: translateX(0px);
}
11.5% {
transform: translateX(0px);
}
20% {
transform: translateX(200px);
}
31.5% {
transform: translateX(200px);
}
40% {
transform: translateX(400px);
}
51.5% {
transform: translateX(400px);
}
60% {
transform: translateX(600px);
}
71.5% {
transform: translateX(600px);
}
80% {
transform: translateX(800px);
}
91.5% {
transform: translateX(800px);
}
100% {
transform: translateX(1000px);
}
}
body {
background-color: #6dba94;
}
<div class="container">
<div><img class="gif-image" src="https://cdn.dribbble.com/users/672882/screenshots/1972683/character-rig-800x600.gif" /></div>
</div>

Related

How to use a subset of animation.css animations?

I want to use https://animate.style/. But it's more than 90 KBs in size.
I just want a very simple bouncing animation. That's all.
Apart from going into the source code and trying to recreate the bouncing keyframes and animations, is there another way to do so?
For example, in Material UI, or in TailwindCSS only what you have used would be included in the final bundle.
Is there something similar for Animate.css too?
If you only need a simple bouncing animation, why not using your own keyframes?
Exemple falling down :
#keyframes myAnim {
0% {
animation-timing-function: ease-in;
opacity: 1;
transform: translateY(-45px);
}
75% {
transform: translateY(10px);
}
100% {
transform: translateY(0px);
}
}
#my_little_square {
width:50px;
height:50px;
background-color:#f00;
animation: myAnim 1s ease 0s 1 normal forwards;
}
<div id="my_little_square">
</div>
Here is a little tool to help you start : https://webcode.tools/generators/css/keyframe-animation

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!

CSS wiggle/shake effect [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
The effect I am intend to do:
-wiggle a few times and stop wiggling. Do this behaviour periodically until mouse is hover.
-on hover, wiggle motion stops completely.
-all transition are smooth out.
I tried with -webkit-animation keyframes, but using -webkit-animation-timing-function to ease out the transition when the mouse is hovered didn t work.
Also, i am lost on how to achieve the period motion of: wiggle, stop, and wiggle again.
I would appreciate if you could point out in the right directions.
Here is a simple wiggle animation that stops when you hover over it.
In order to achieve a delay between wiggles, you can just include an "empty chunk" of the animation... that is, a period during which nothing changes. In my example, nothing changes between the 0% and 80% mark, and the "wiggle" only occurs in the last 20% (which ends up coming out to half a second).
#keyframes wiggle {
0% { transform: rotate(0deg); }
80% { transform: rotate(0deg); }
85% { transform: rotate(5deg); }
95% { transform: rotate(-5deg); }
100% { transform: rotate(0deg); }
}
h1.wiggle {
display: inline-block;
animation: wiggle 2.5s infinite;
}
h1.wiggle:hover {
animation: none;
}
<h1 class="wiggle">
wiggle, wiggle
</h1>
Unfortunately, this doesn't account for "easing" back into the un-wiggled state if you hover over it mid-animation. Doing so might require a bit of JavaScript.
Try one of the following:
.class:hover {
animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both;
transform: translate3d(0, 0, 0);
backface-visibility: hidden;
perspective: 1000px;
}
#keyframes shake {
10%, 90% {
transform: translate3d(-1px, 0, 0);
}
20%, 80% {
transform: translate3d(2px, 0, 0);
}
30%, 50%, 70% {
transform: translate3d(-4px, 0, 0);
}
40%, 60% {
transform: translate3d(4px, 0, 0);
}
}
https://css-tricks.com/snippets/css/shake-css-keyframe-animation/
or
Add This to your Script : <link type="text/css" href="https://rawgit.com/elrumordelaluz/csshake/master/dist/csshake.min.css"></link>
And Add a class to the element you want to shake
Full Documentation here: https://elrumordelaluz.github.io/csshake/

CSS perspective with rotate & translate issue

I am attempting to make a type of CSS only slide transition from one content section to another. In order to do so in an interesting way, I use CSS's perspective and rotateX to in essence lay down the page content. I then am trying to slide the content out towards the bottom of the screen using translateY
Separately, both the translateY and the rotateX work perfectly, no matter what the perspective is. However, when combined, it only works with certain perspectives based on the window size and rotateY value
In this jsFiddle it works as I would like it to in the window sizes I have tried. The problem is that I would like the perspective value to be lower, around 250px, but I cannot do so without breaking the animation.
I tried using a higher rotateY degree instead of making the perspective lower but the same issue occurs
#keyframes slide {
0% { transform: perspective(450px); }
25% { transform: perspective(450px) rotateX(30deg); }
50%,100% { transform: perspective(450px) rotateX(30deg) translateY(100%); }
}
I have tested this on CSS Deck and jsFiddle both in FireFox and Chrome and it seems to be a consistent issue
Can anyone provide me with a reason why this is happening and offer a work around?
Try setting the perspective as a separate rule on a parent element (as opposed to being part of the transform in the animation).
.parent {
perspective: 250px;
}
#keyframes slide {
25% { transform: rotateX(30deg); }
50%, 100% { transform: rotateX(30deg) translateY(100%); }
}
Updated fiddle: http://jsfiddle.net/myajouri/DYpnU/
My reasoning:
The perspective does not change during the animation so there's no point in having it as part of the animation.
Since your elements occupy 100% of the parent's area, setting the perspective on the parent should produce the same result as setting it on the elements themselves (inside transform).
It seems to solve your problem (see fiddle above).
UPDATE: after more experimentation, I found that explicitly setting the translateY(0) initial value in the animation would solve the issue as well.
#keyframes slide {
0% { transform: perspective(150px); }
25% { transform: perspective(150px) rotateX(30deg) translateY(0); }
50%, 100% { transform: perspective(150px) rotateX(30deg) translateY(100%); }
}
Updated fiddle: http://jsfiddle.net/myajouri/YJS3v/
Only a slight improvement over myajouri answer.
At leats in Chrome, you can write
#-webkit-keyframes slide {
0% { -webkit-transform: perspective(50vh); }
10%,15% { -webkit-transform: perspective(50vh) rotateX(30deg) translateY(0%); }
50%,100% { -webkit-transform: perspective(50vh) rotateX(30deg) translateY(100%); }
}
Setting the perspective to the viewport height should make it more responsive that your current setting
demo
(Untested in other browsers)

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