I am making a menu that should have animated "hamburger" icon inside. At first, I used transform and it looked nice, but I decided to add some fancier animation ;-)
They loook like this:
#keyframes animateFirstBar {
0% {
transform: translate(-50%, -200%);
}
50% {
transform: translate(-50%, 0);
}
100% {
transform: translateX(-50%) rotate(-45deg);
}
}
#keyframes animateSecoundBar {
0%, 50% {
transform: translate(-50%, 0);
}
51%, 100% {
transform: translate(-50%, 0) scaleX(.01);
}
}
#keyframes animateThirdBar {
0% {
transform: translate(-50%, 200%);
}
50% {
transform: translate(-50%, 0);
}
100% {
transform: translateX(-50%) rotate(45deg);
}
}
And they are used like this:
.main-menu {
$mainMenu: &;
position: fixed;
width: 300px;
height: 100%;
top: 0;
left: 0;
background: #ccc;
transform: translateX(-100%);
transition: $time transform ease-in;
&--active {
transform: none;
#{$mainMenu}__toggle {
transform: none;
background: rgba(0, 0, 0, 0);
}
#{$mainMenu}__toggle-line {
&:nth-of-type(1) {
animation: $time animateFirstBar forwards;
}
&:nth-of-type(2) {
animation: $time animateSecoundBar forwards;
}
&:nth-of-type(3) {
animation: $time animateThirdBar forwards;
}
}
}
&__toggle {
width: $width;
height: $width - 1;
position: absolute;
right: 0;
transform: translateX(100%);
top: 0;
background: yellow;
border: 0;
outline: 0;
transition: $time transform ease-in, $time background linear;
transform-origin: bottom right;
}
&__toggle-line {
width: 60%;
height: $lineHeight;
display: block;
background: black;
position: absolute;
left: 50%;
transition: $time transform ease-in;
top: (50% - ($lineHeight/2));
&:nth-of-type(1) {
animation: none;
transform: translate(-50%, -200%);
}
&:nth-of-type(2) {
animation: none;
transform: translate(-50%, 0);
}
&:nth-of-type(3) {
animation: none;
transform: translate(-50%, 200%);
}
}
}
You can see the example here: http://codepen.io/tomekbuszewski/pen/jrzKKR?editors=0100
My problem is, I don't know how to revert the animation on "exit" (on removing the --active modificator). I don't want to write another animations or add another class that will be removed over time with JS.
Previously I have already implemented this hamburger button with transition and transform and I think it is satisfied what you want to archive. I haven't done it with your approach using animation. But please take a look at this snippet to see the idea.
function toggleMenu(x) {
x.classList.toggle("change");
}
/*
Orginal article - https://github.com/trungk18/Animated-Navigation-Menu-Icons-with-CSS3
*/
/*Menu container*/
.content {
max-width: 40em;
margin: 1em auto;
}
.icon-container {
float: left;
position: relative;
cursor: pointer;
margin: 0 5em 5em;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
transition: all 0.3s;
}
.bar {
display: block;
width: 35px;
height: 5px;
background-color: #333;
margin: 6px auto;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
transition: all 0.3s;
border-radius: 3px;
}
.change {
/*Rotate first bar*/
/*Fade out the second bar-*/
/*Reduce width the second bar-*/
/*Rotate last bar*/
}
.change.icon-5 {
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-ms-transform: rotate(180deg);
-o-transform: rotate(180deg);
transform: rotate(180deg);
}
.change .bar-10 {
-webkit-transform: rotate(45deg) translate(8px, -3px) scaleX(0.7);
-moz-transform: rotate(45deg) translate(8px, -3px) scaleX(0.7);
-ms-transform: rotate(45deg) translate(8px, -3px) scaleX(0.7);
-o-transform: rotate(45deg) translate(8px, -3px) scaleX(0.7);
transform: rotate(45deg) translate(8px, -3px) scaleX(0.7);
}
.change .bar-12 {
-webkit-transform: rotate(-45deg) translate(8px, 3px) scaleX(0.7);
-moz-transform: rotate(-45deg) translate(8px, 3px) scaleX(0.7);
-ms-transform: rotate(-45deg) translate(8px, 3px) scaleX(0.7);
-o-transform: rotate(-45deg) translate(8px, 3px) scaleX(0.7);
transform: rotate(-45deg) translate(8px, 3px) scaleX(0.7);
}
<section class="content">
<div class="icon-container icon-5" onclick="toggleMenu(this)">
<span class="bar bar-10"></span>
<span class="bar bar-11"></span>
<span class="bar bar-12"></span>
</div>
</section>
<!--Full pen: http://codepen.io/trungk18/pen/jrrXjz-->
I've managed to solve the problem. I had to add another class, trigger it with JS and write another set of animations that flowed in reverse.
Animations:
#keyframes animateFirstBar {
0% { transform: translate(-50%, $spacing * -100%); }
60% { transform: translate(-50%, 0); }
100% { transform: translateX(-50%) rotate(-#{$rotation}deg); }
}
#keyframes revertFirstBar {
100% { transform: translate(-50%, $spacing * -100%); }
60% { transform: translate(-50%, 0); }
0% { transform: translateX(-50%) rotate(-#{$rotation}deg); }
}
#keyframes animateSecoundBar {
0%, 60% { transform: translate(-50%, 0); }
61%, 100% { transform: translate(-50%, 0) scaleX(.01); }
}
#keyframes revertSecoundBar {
0%, 60% { transform: translate(-50%, 0) scaleX(.01); }
61%, 100% { transform: translate(-50%, 0); }
}
#keyframes animateThirdBar {
0% { transform: translate(-50%, $spacing * 100%); }
60% { transform: translate(-50%, 0); }
100% { transform: translateX(-50%) rotate(#{$rotation}deg); }
}
#keyframes revertThirdBar {
0% { transform: translateX(-50%) rotate(#{$rotation}deg); }
60% { transform: translate(-50%, 0); }
100% { transform: translate(-50%, $spacing * 100%); }
}
revert*Bar are going with one class, animate*Bar with another.
Related
I have never done animations in CSS, what I'm trying to get is something like cog's animations two circles spinning, one to the right and the other to the left without overlapping...
I think I got the animation(sort of) but not the drawing I think..
I have this demo: https://jsfiddle.net/Tankers/8dxh94zp/9/
the "figures" are correct and the location also correct but the animation is not.
when they spin it overlaps may be is because the object are not 100% squares?, what need to be visible is just half circles just the way that is in my demo..
HTML
<div class="wrap">
<div class="top"></div>
<div class="bott"></div>
</div>
CSS
#keyframes half_spin {
0% {
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
40% {
-ms-transform: rotate(20deg);
-moz-transform: rotate(20deg);
-webkit-transform: rotate(20deg);
-o-transform: rotate(20deg);
transform: rotate(20deg);
}
60% {
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
80% {
-ms-transform: rotate(-20deg);
-moz-transform: rotate(-20deg);
-webkit-transform: rotate(-20deg);
-o-transform: rotate(-20deg);
transform: rotate(-20deg);
}
100% {
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
}
.wrap {
display: block;
overflow: hidden;
position: relative
}
.top {
width: 300px;
height: 150px;
border: 1px solid red;
border-bottom-left-radius: 151px;
border-bottom-right-radius: 151px;
position: relative;
animation: half_spin 5000ms ease-in-out infinite;
}
.top:before {
position: absolute;
width: 100%;
height: 1px;
background: red;
content: " ";
top: 0;
left: 0;
}
.bott {
width: 300px;
height: 150px;
border: 1px solid black;
border-top-left-radius: 151px;
border-top-right-radius: 151px;
animation: half_spin 5000ms ease-in-out infinite reverse;
position: relative;
}
.bott:before {
position: absolute;
width: 100%;
height: 1px;
background: black;
content: " ";
bottom: 0;
left :0;
}
If I understand your question correctly, this code snippet is what you're looking for. I added a transform-origin property to both the top and bottom half-circles to specify the point that we're rotating around.
Both divs should rotate around the midpoint of their flat edge, for the top that is transform-origin: 50% 0%; and for the bottom it is transform-origin: 50% 100%;
#keyframes half_spin {
0% {
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
40% {
-ms-transform: rotate(20deg);
-moz-transform: rotate(20deg);
-webkit-transform: rotate(20deg);
-o-transform: rotate(20deg);
transform: rotate(20deg);
}
60% {
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
80% {
-ms-transform: rotate(-20deg);
-moz-transform: rotate(-20deg);
-webkit-transform: rotate(-20deg);
-o-transform: rotate(-20deg);
transform: rotate(-20deg);
}
100% {
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
}
.wrap {
display: block;
overflow: hidden;
position: relative
}
.top {
width: 300px;
height: 150px;
border: 1px solid red;
border-bottom-left-radius: 151px;
border-bottom-right-radius: 151px;
position: relative;
animation: half_spin 5000ms ease-in-out infinite;
transform-origin: 50% 0%;
}
.top:before {
position: absolute;
width: 100%;
height: 1px;
background: red;
content: " ";
top: 0;
left: 0;
}
.bott {
width: 300px;
height: 150px;
border: 1px solid black;
border-top-left-radius: 151px;
border-top-right-radius: 151px;
animation: half_spin 5000ms ease-in-out infinite;
position: relative;
transform-origin: 50% 100%;
}
.bott:before {
position: absolute;
width: 100%;
height: 1px;
background: black;
content: " ";
bottom: 0;
left :0;
}
<div class="wrap">
<div class="top">
</div>
<div class="bott">
</div>
</div>
I have an element that should come towards the user in front of the screen but also like falling from above.
I have tried transitioning from rotateX(-90deg) to rotateX(0) and from rotateX(360deg) to rotateX(270deg), but it does not look the way I want.
Also I do not what would be a good way to search for this on Google.
Sketch
Source code
body {
margin: 0 0;
}
.my-class-here {
width: 100%;
height: 100vh;
animation-name: header-anim;
animation-duration: 5s;
width: 200px;
height: 200px;
background-color: yellow;
text-align: center;
}
#keyframes header-anim {
0% {
transform: rotateX(360deg);
}
100% {
transform: rotateX(270deg);
}
}
<div class="my-class-here">
TEST
</div>
How can I achieve this?
Thank you!
You need to correct your transform-origin and add some perspective:
body {
margin: 0 0;
}
.my-class-here {
animation: header-anim 2s;
width: 200px;
height: 200px;
background-color: yellow;
text-align: center;
transform-origin:top; /* don't forget this */
}
#keyframes header-anim {
0% {
transform: perspective(200px) rotateX(270deg);
}
100% {
transform: perspective(200px) rotateX(360deg);
}
}
<div class="my-class-here">
TEST
</div>
I believe that this is what you're looking for.
#-webkit-keyframes slide-in-fwd-tr {
0% {
-webkit-transform: translateZ(-1400px) translateY(-800px) translateX(1000px);
transform: translateZ(-1400px) translateY(-800px) translateX(1000px);
opacity: 0;
}
100% {
-webkit-transform: translateZ(0) translateY(0) translateX(0);
transform: translateZ(0) translateY(0) translateX(0);
opacity: 1;
}
}
#keyframes slide-in-fwd-tr {
0% {
-webkit-transform: translateZ(-1400px) translateY(-800px) translateX(1000px);
transform: translateZ(-1400px) translateY(-800px) translateX(1000px);
opacity: 0;
}
100% {
-webkit-transform: translateZ(0) translateY(0) translateX(0);
transform: translateZ(0) translateY(0) translateX(0);
opacity: 1;
}
}
How you see in code my span after 'opacity:0 and rotate()' goes up, then it have to 'scale and opacity: 0' and after that go to down. But it does not goes like that, it quickly before 'scale and opacity' goes down.
Just look at how it works
I don't have many experience with animations but I can not understand, that code have to work properly. But it lose its direction
The link in my commentary
#keyframes for_box2 {
0% {
opacity: 1;
}
3% {
opacity: .5;
}
5% {
opacity: .2;
transform: rotateY(90deg);
}
8% {
opacity: 0;
transform: rotateY(180deg);
}
10% {
transform: translateY(-50%);
}
12% {
transform: translateY(-100%);
}
14% {
transform: translateY(-150%);
}
16% {
transform: translateY(-200%);
}
18% {
transform: scale(.95);
}
20% {
transform: scale(1);
}
22% {
transform: scale(1.25);
}
24% {
transform: scale(1.1);
}
26% {
transform: scale(1);
opacity: .8;
}
28% {
opacity: .5;
transform: rotateY(90deg);
}
30% {
opacity: .2;
transform: rotateY(120deg)
}
32% {
opacity: 0;
transform: rotateY(180deg)
}
40% {
animation-timing-function: ease-out;
transform: translateX(-50%);
transform: rotateY(180deg);
}
48% {
transform: translateX(-120%);
}
56% {
opacity: 1;
transform: rotateY(0deg);
}
64% {
opacity: 0;
transform: rotateY(180deg);
}
72% {
transform: translateY(-200%);
animation-timing-function: cubic-bezier(.01,1.42,.02,1);
}
80% {
opacity: 1;
transform: rotateY(0deg);
}
88% {
opacity: 0;
transform: rotateY(180deg);
}
94% {
transform: translateY(0);
animation-timing-function: cubic-bezier(.01,1.42,.02,1);
}
100% {
transform: rotateY(0deg);
opacity: 1;
}
}
https://codepen.io/babken-asryan/pen/XvbdXB
You need to put all the transformation in the same transform or you will simply override them:
body {
margin: 0;
position: relative;
overflow-x: hidden;
box-sizing: border-box;
}
.wrapper {
transition: .7s;
border: solid #357ae8;
transform: rotate(-.5deg);
padding: 0 !important;
}
.wrapper .inside {
background: linear-gradient(288deg, rgba(233, 26, 93, 0.8883928571428571) 0%, rgba(255, 241, 29, 0.9220063025210083) 36%, rgba(231, 235, 70, 1) 51%, rgba(255, 247, 117, 1) 68%, rgba(156, 233, 247, 0.9472163865546218) 91%);
border: solid #357ae8;
background-size: 400% 400%;
transform: rotate(.5deg);
display: block;
width: 350px;
height: 500px;
animation: Gradient 15s ease infinite;
}
.wrapper .inside span {
display: block;
width: 40%;
height: 30%;
position: absolute;
}
.wrapper .inside span.box2 {
bottom: 5%;
right: 5%;
background: url('https://svgur.com/i/EAo.svg') no-repeat;
-webkit-background-size: cover;
background-size: cover;
background-position: center;
animation: for_box2 linear 45s 1s infinite;
}
#keyframes Gradient {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
#keyframes for_box2 {
0% {
opacity: 1;
}
3% {
opacity: .5;
}
5% {
opacity: .2;
transform: translateX(0) translateY(0) rotateY(90deg);
}
8% {
opacity: 0;
transform: translateX(0) translateY(0) rotateY(180deg);
}
10% {
transform: translateX(0) translateY(-50%) rotateY(180deg);
}
12% {
transform: translateX(0) translateY(-100%) rotateY(180deg);
}
14% {
transform: translateX(0) translateY(-150%) rotateY(180deg);
}
16% {
transform: translateX(0)translateY(-200%) rotateY(180deg);
}
18% {
transform: translateX(0) translateY(-200%) rotateY(180deg) scale(.95);
}
20% {
transform: translateX(0) translateY(-200%) rotateY(180deg) scale(1);
}
22% {
transform: translateX(0) translateY(-200%) rotateY(180deg) scale(1.25);
}
24% {
transform: translateX(0) translateY(-200%) rotateY(180deg) scale(1.1);
}
26% {
transform: translateX(0) translateY(-200%) rotateY(180deg) scale(1);
opacity: .8;
}
28% {
opacity: .5;
transform: translateX(0) translateY(-200%) rotateY(90deg);
}
30% {
opacity: .2;
transform: translateX(0) translateY(-200%) rotateY(120deg);
}
32% {
opacity: 0;
transform: translateX(0) translateY(-200%)rotateY(180deg);
}
40% {
animation-timing-function: ease-out;
transform: translateX(-50%) translateY(-200%) rotateY(180deg);
}
48% {
transform: translateX(-120%) translateY(-200%) rotateY(180deg);
}
56% {
opacity: 1;
transform: translateX(-120%) translateY(-200%) rotateY(0deg);
}
64% {
opacity: 0;
transform: translateX(-120%) translateY(-200%) rotateY(180deg);
}
72% {
transform: translateX(-120%) translateY(-200%) rotateY(180deg);
animation-timing-function: cubic-bezier(.01, 1.42, .02, 1);
}
80% {
opacity: 1;
transform: translateX(-120%) translateY(-200%) rotateY(0deg);
}
88% {
opacity: 0;
transform: translateX(-120%) translateY(-200%) rotateY(180deg);
}
94% {
transform: translateX(-120%) translateY(0) rotateY(180deg);
animation-timing-function: cubic-bezier(.01, 1.42, .02, 1);
}
100% {
transform: translateX(-120%) translateY(0) rotateY(0deg);
opacity: 1;
}
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<body>
<div class="container-fluid mt-5">
<div class="row d-flex justify-content-around">
<div class="d-inline-flex p-2 wrapper">
<div class="d-inline-flex p-2 inside">
<span class="box2"></span>
</div>
</div>
</div>
All is in the title, I cannot figure out why my animation is working everywhere but not in IE and edge. Where am I missing something ?
Here are the keyframes of my animation and the JS fiddle associated
$(document).ready(function () {
$('#toggle').hide();
});
$('#toggler').click(function () {
$("#toggle").delay(800).velocity("slideDown", {
duration: 1200
});
$("#footer").delay(800).velocity("scroll", {
duration: 1200
});
});
body {
overflow-x:hidden;
overflow-y:scroll;
}
#content1 {
width:100%;
height:800px;
background-color:grey;
position:relative;
}
#toggler {
position: absolute;
left: 0;
right: 0;
bottom:10px;
margin-left: auto;
margin-right: auto;
width: 100px;
height:50px;
}
#footer {
background-color:black;
width:100%;
height:150px;
}
.slide-up {
display: block;
height: auto;
width:100%;
}
.animate {
animation: super-zgeger-mob 5s;
animation-timing-function: linear;
animation-iteration-count: 1;
transform-origin: 50% 50%;
z-index: 9999;
overflow: hidden;
-webkit-animation: super-zgeger-mob linear 5s;
-webkit-animation-iteration-count: 1;
-webkit-transform-origin: 50% 50%;
-webkit-animation-fill-mode: forwards;
-moz-animation: super-zgeger-mob linear 5s;
-moz-animation-iteration-count: 1;
-moz-transform-origin: 50% 50%;
-moz-animation-fill-mode: forwards;
-o-animation: super-zgeger-mob linear 5s;
-o-animation-iteration-count: 1;
-o-transform-origin: 50% 50%;
-o-animation-fill-mode: forwards;
-ms-animation: super-zgeger-mob linear 5s;
-ms-animation-iteration-count: 1;
-ms-transform-origin: 50% 50%;
-ms-animation-fill-mode: forwards;
}
#keyframes super-zgeger-mob {
0% {
transform: translate(-90%, 0%);
opacity: 0;
}
15% {
transform: translate(-90%, 0%);
opacity: 1;
}
50% {
transform: translate(0%, 0%);
}
75% {
transform: translate(-5%, 0%) rotate(10deg);
}
100% {
transform: translate(150%, 0%);
}
}
#-moz-keyframes super-zgeger-mob {
0% {
-moz-transform: translate(-90%, 0%);
opacity: 0;
}
15% {
-moz-transform: translate(-90%, 0%);
opacity: 1;
}
50% {
-moz-transform: translate(0%, 0%);
}
75% {
-moz-transform: translate(-5%, 0%) rotate(10deg);
}
100% {
-moz-transform: translate(150%, 0%);
}
}
#-webkit-keyframes super-zgeger-mob {
0% {
-webkit-transform: translate(-90%, 0%);
opacity: 0;
}
15% {
-webkit-transform: translate(-90%, 0%);
opacity: 1;
}
50% {
-webkit-transform: translate(0%, 0%);
}
75% {
-webkit-transform: translate(-5%, 0%) rotate(10deg);
}
100% {
-webkit-transform: translate(150%, 0%);
}
}
#-o-keyframes super-zgeger-mob {
0% {
-o-transform: translate(-90%, 0%);
opacity: 0;
}
15% {
-o-transform: translate(-90%, 0%);
opacity: 1;
}
50% {
-o-transform: translate(0%, 0%);
}
75% {
-o-transform: translate(-5%, 0%) rotate(10deg);
}
100% {
-o-transform: translate(150%, 0%);
}
}
#-ms-keyframes super-zgeger-mob {
0% {
-ms-transform: translate(-90%, 0%);
opacity: 0;
}
15% {
-ms-transform: translate(-90%, 0%);
opacity: 1;
}
50% {
-ms-transform: translate(0%, 0%);
}
75% {
-ms-transform: translate(-5%, 0%) rotate(10deg);
}
100% {
-ms-transform: translate(150%, 0%);
}
}
<div id=content1>
<button id="toggler">
push me
</button>
</div>
<div id="toggle">
<div id="animation" style="position: relative; left: 0; top: 0;">
<img src="http://image.gilawhost.com/16/11/09/jzjhk7o0.png" class="slide-up"/>
<img id="rolling" src="http://image.gilawhost.com/16/11/09/6d7tsk5k.png" class="slide-up animate" style="position: absolute; top: 0%; left: 0%; z-index: 99;" />
</div>
</div>
<div id=footer>
</div>
I guess, Using positioning on .animate (left:-90% to desired position) over translate() property will work for you.
translate partially supported by IE 11 only and in opera its also wont work properly.
http://caniuse.com/#feat=transforms2d.
I would like a div to animate to the right when a button is clicked, then animate again to the left when the same button is clicked. I would like to use only one keyframes declaration. Is this possible by swapping classes?
I've tried this in CodePen, but unfortunately, the div snaps back after the first animation, then refuses to animate the second time.
I'm not using CSS transitions because I want to be able to use features of CSS animations like a bouncing effect.
window.addEventListener("load", function() {
var movedOver = false;
document.querySelector("button").addEventListener("click", function() {
var buttonEl = document.querySelector(".one");
if (movedOver) {
buttonEl.classList.remove("do-the-slide");
buttonEl.classList.add("do-the-slide-back");
} else {
buttonEl.classList.remove("do-the-slide-back");
buttonEl.classList.add("do-the-slide");
}
});
});
.container {
position: absolute;
perspective: 800px;
>div {
position: absolute;
padding: 20px;
text-align: center;
width: 100px;
}
>div.do-the-slide {
animation: moveOver 1s ease-out;
}
>div.do-the-slide-back {
animation: moveOver 1s reverse ease-out;
}
>.one {
background: red;
}
}
button {
margin-top: 100px;
}
#keyframes moveOver {
from {
transform: translateX(0px);
}
to {
transform: translateX(100px);
}
}
<div class="container">
<div class="one">One</div>
</div>
<button>Clicky</button>
Codepen: http://codepen.io/anon/pen/Vaadao
Alright, so after fiddling with this for a while, I've come up with what I consider an acceptable solution for using one keyframes declaration to drive both directions of animations. The key to this was forcing the browser essentially reset through a redraw, as explained here: https://css-tricks.com/restart-css-animation/ (thank you Jacob Gray for posting that reference).
Once I got that working with the reset, I used javascript (yes, this requires javascript) to add the reverse direction when animating back (this could be in a separate class and just add that className).
And, it works. I'm now able to animate in both directions using one keyframes declaration. Pretty snazzy, and drastically minimizes the css code.
window.addEventListener("load", function() {
var movedOver = false;
var direction = "";
document.querySelector("button").addEventListener("click", function() {
var el = document.querySelector(".one");
el.classList.remove("do-the-slide");
el.offsetWidth = el.offsetWidth;
if (direction === "toRight") {
direction = "toLeft";
el.style.animationDirection = "reverse";
} else {
direction = "toRight";
el.style.animationDirection = "";
}
el.classList.add("do-the-slide");
});
});
.container {
position: absolute;
perspective: 800px;
>div {
position: absolute;
padding: 20px;
text-align: center;
width: 100px;
}
>div.do-the-slide {
animation: moveOver 1s ease-in-out;
animation-fill-mode: forwards;
}
>.one {
background: red;
}
}
button {
margin-top: 100px;
}
#keyframes moveOver {
from {
transform: translate3d(0px, 0, 0);
}
20% {
transform: translate3d(-20px, 0, 0);
}
80% {
transform: translate3d(120px, 0, 0);
}
to {
transform: translate3d(100px, 0, 0);
}
}
<div class="container">
<div class="one">One</div>
</div>
<button>Clicky</button>
CodePen: http://codepen.io/risingtiger/pen/zqqMpv
Maybe you are looking for forwards, but even then, a transition will be needed to make it simple.
p span {
display: inline-block;
transition: 1s;
}
p:hover span {
animation: 1s moveOver forwards;
}
#keyframes moveOver {
to {
transform: translateX(100px);
}
<p><span>span</span>
</p>
I f you want to use a single animation, you will eventually have to deal with paused and steps and i m not even sure that will be easy to handle or possible. I see no fun here :)
for a bounce effect, final value at 50% should be good enough:
p span {
display: inline-block;
transition: 1s;
}
p:hover span {
animation: 2s moveOver infinite;
}
#keyframes moveOver {
50% {
transform: translateX(100px);
}
<p><span>span</span>
</p>
I made a pen based on this post and the css-tricks article here codepen
HTML
<h2>Single keyframe-track burger collection</h2>
<p>(each span uses only one track to play for- and backwards)</p>
<div class="wrapper">
<div class="cell">
<h3>Default</h3>
<div>
<button class="burger">
<span class="burger__bar"></span>
<span class="burger__bar"></span>
<span class="burger__bar"></span>
</button>
</div>
</div>
<div class="cell">
<h3>Merge</h3>
<div>
<button class="burger burger--merge">
<span class="burger__bar"></span>
<span class="burger__bar"></span>
<span class="burger__bar"></span>
</button>
</div>
</div>
<div class="cell">
<h3>Rotate</h3>
<div>
<button class="burger burger--rotate">
<span class="burger__bar"></span>
<span class="burger__bar"></span>
<span class="burger__bar"></span>
</button>
</div>
</div>
<div class="cell">
<h3>Spin</h3>
<div>
<button class="burger burger--spin">
<span class="burger__bar"></span>
<span class="burger__bar"></span>
<span class="burger__bar"></span>
</button>
</div>
</div>
</div>
CSS
body {
position: relative;
padding: 0;
margin: 0;
width: 100%;
height: 100vh;
background: radial-gradient(#5E802B, #2F4016);
font-family: sans-serif;
text-align: center;
h2,
h3,
p {
color: rgb(255, 255, 255);
}
}
.wrapper {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
}
.cell {
flex-grow: 1;
flex-basis: 50%;
margin: 0 20px;
display: flex;
flex-direction: column;
div {
margin-top: auto;
}
}
/****************
* Burger Styles *
*****************/
.burger {
position: relative;
width: 60px;
height: 60px;
padding: 0;
border: none;
background-color: transparent;
&__bar {
height: 10%;
border-radius: 2px;
width: 80%;
background-color: white;
display: block;
position: absolute;
left: 50%;
animation-timing-function: ease-in-out;
animation-play-state: paused;
animation-duration: .4s;
animation-fill-mode: both;
&:nth-child(1) {
top: 25%;
transform: translate(-50%, 0%);
}
&:nth-child(2) {
top: 50%;
transform: translate(-50%, -50%);
}
&:nth-child(3) {
bottom: 25%;
transform: translate(-50%, 0%);
}
}
&.close .burger__bar {
animation-direction: reverse;
}
&.open .burger__bar {
animation-direction: normal;
}
// default
&.animate .burger__bar {
animation-play-state: running;
&:nth-child(1) {
animation-name: default-top;
}
&:nth-child(2) {
animation-name: default-middle;
}
&:nth-child(3) {
animation-name: default-bottom;
}
}
&--merge.animate .burger__bar {
animation-duration: .6s;
animation-timing-function: ease;
&:nth-child(1) {
animation-name: merge-top;
}
&:nth-child(2) {
animation-name: merge-middle;
}
&:nth-child(3) {
animation-name: merge-bottom;
}
}
&--rotate.animate .burger__bar {
&:nth-child(1) {
animation-name: rotate-top;
}
&:nth-child(2) {
animation-name: rotate-middle;
}
&:nth-child(3) {
animation-name: rotate-bottom;
}
}
&--spin.animate .burger__bar {
animation-duration: 1s;
animation-timing-function: ease;
&:nth-child(1) {
animation-name: spin-top;
}
&:nth-child(2) {
animation-name: spin-middle;
}
&:nth-child(3) {
animation-name: spin-bottom;
}
}
}
/*__________________
DEFAULT
____________________*/
#keyframes default-top {
50% {
top:50%;
transform: translate(-50%, -50%) rotate(0);
}
100% {
top:50%;
transform: translate(-50%, -50%) rotate(-45deg);
}
}
#keyframes default-middle {
50%, 100% {visibility:hidden;}
}
#keyframes default-bottom {
0% {}
25% {}
50% {
bottom:50%;
transform: translate(-50%, -50%) rotate(0deg);
}
100% {
bottom:50%;
transform: translate(-50%, 50%) rotate(45deg);
}
}
/*__________________
MERGE
____________________*/
#keyframes merge-top {
20% {
top:50%;
transform: translate(-50%, -50%) rotate(0) scale(1, 1);
//width: 100%;
}
50% {
transform: translate(-50%, -50%) rotate(0) scale(0.2, 1);
//width: 20%;
}
60% {
transform: translate(-50%, -50%) rotate(-45deg) scale(0.2, 1);
//width: 20%;
}
100% {
top:50%;
transform: translate(-50%, -50%) rotate(-45deg) scale(1, 1);
//width: 100%;
}
}
#keyframes merge-middle {
50% {
transform: translate(-50%, -50%) scale(0, 1);
}
51%{visibility:hidden;}
99% {
transform: translate(-50%, -50%) scale(0, 1);
}
100% {visibility:hidden;}
}
#keyframes merge-bottom {
20% {
bottom:40%;
transform: translate(-50%, -50%) rotate(0deg) scale(1, 1);
}
50% {
transform: translate(-50%, -50%) rotate(0deg) scale(0.2, 1);
}
60% {
transform: translate(-50%, -50%) rotate(45deg) scale(0.2, 1);
}
100% {
bottom:40%;
transform: translate(-50%, -50%) rotate(45deg) scale(1, 1);
}
}
/*__________________
ROTATE
____________________*/
#keyframes rotate-top {
50% {
top:50%;
transform: translate(-50%, -50%) rotate(0deg);
}
100% {
top:50%;
transform: translate(-50%, -50%) rotate(45deg);
}
}
#keyframes rotate-middle {
50% {transform: translate(-50%, -50%) rotate(0deg);}
100% {transform: translate(-50%, -50%) rotate(135deg);}
}
#keyframes rotate-bottom {
50% {
bottom:50%;
transform: translate(-50%, 50%) rotate(0deg);
}
100% {
bottom:50%;
transform: translate(-50%, 50%) rotate(45deg);
}
}
/*__________________
SPIN
____________________*/
#keyframes spin-top {
50% {
top:50%;
transform: translate(-50%, -50%) rotate(0deg);
}
75% {
transform: translate(-50%, -50%) rotate(360deg);
}
100% {
top:50%;
transform: translate(-50%, -50%) rotate(315deg);
}
}
#keyframes spin-middle {
50% {visibility:hidden;}
100% {visibility:hidden;}
}
#keyframes spin-bottom {
50% {
bottom:50%;
transform: translate(-50%, 50%) rotate(0deg);
}
75% {
transform: translate(-50%, 50%) rotate(450deg);
}
100% {
bottom:50%;
transform: translate(-50%, 50%) rotate(405deg);
}
}
Javascript
burgers = document.querySelectorAll('.burger');
for (let i = 0; i < burgers.length; i++) {
burgers[i].addEventListener("click", function(){
this.classList.remove("animate");
var bars = this.querySelectorAll('.burger__bar');
for (let i = 0; i < bars.length; i++) {
// Reset span animations - https://css-tricks.com/restart-css-animation/
void bars[i].offsetWidth;
}
if (this.classList.contains("open")){
this.classList.remove("open");
this.classList.add("close");
} else {
this.classList.remove("close");
this.classList.add("open");
}
this.classList.add("animate");
});
};