Reverse animations aren't working properly with javascript and keyframes - javascript

I'm trying to animate the navigation overlay to come in from the right (which is working perfectly!), but it's not working when I try to reverse the process. I'm wondering why. Please review the code below and see if you can help me.
HTML
<nav class="nav-element">
<h1>header</h1>
<figure class="nav-img">
<img src="images/svg/menu.svg" alt="Hamburger Menu" id="nav-open">
</figure>
</nav>
<section id="overlay" class="overlay">
<header>
<h1>Header</h1>
<figure class="nav-img">
<img src="images/svg/menu-close.svg" alt="Close Menu" id="nav-close">
</figure>
</header>
<ul>
<li class="nav-button">item 1</li>
<li class="nav-button">item 2</li>
<li class="nav-button">item 3</li>
<li class="nav-button">item 4</li>
</ul>
</section>
SCSS
.show-menu {
display: block;
animation: slide-menu 0.5s ease-in forwards;
header {
animation: show-x 1s 0.5s forwards;
}
li:nth-of-type(1) {
animation: item-1 0.5s 0.5s linear forwards;
}
li:nth-of-type(2) {
animation: item-1 0.5s 0.7s linear forwards;
}
li:nth-of-type(3) {
animation: item-1 0.5s 0.9s linear forwards;
}
li:nth-of-type(4) {
animation: item-1 0.5s 1.1s linear forwards;
}
}
.hide-menu {
display: block;
animation: slide-menu 0.5s 1.1s ease-in forwards;
header {
animation: hide-x 1s 0.5s forwards;
}
li:nth-of-type(1) {
animation: item-hide 0.5s linear forwards;
}
li:nth-of-type(2) {
animation: item-hide 0.5s 0.9s linear forwards;
}
li:nth-of-type(3) {
animation: item-hide 0.5s 0.7s linear forwards;
}
li:nth-of-type(4) {
animation: item-hide 0.5s 0.5s linear forwards;
}
}
#keyframes slide-menu {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
#keyframes show-x {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes item-1 {
from {
transform: translateX(10%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
#keyframes hide-menu {
from {
transform: scaleX(1);
}
to {
transform: scaleX(0);
}
}
#keyframes hide-x {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
#keyframes item-hide {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(10%);
opacity: 0;
}
}
Javascript
const overlay = document.getElementById('overlay');
document.getElementById('nav-open').addEventListener('click', function() {
overlay.classList.add('show-menu');
})
document.getElementById('nav-close').addEventListener('click', function() {
overlay.classList.add('hide-menu');
overlay.classList.remove('show-menu');
})
Can anyone help me why the animation isn't "reversed" and the menu closes the same way it opens?
So first the items move on the X-axis and disappear, then the header content fades, and lastly the overlay moves from the X-axis and disappears.

Try this CSS for the .hide-menu, Adding the reverse property will reverse the animation when clicking the hide button:
.hide-menu {
display: block;
animation: slide-menu 0.5s 1.1s ease-in reverse;
header {
animation: hide-x 1s 0.5s reverse;
}
li:nth-of-type(1) {
animation: item-hide 0.5s linear reverse;
}
li:nth-of-type(2) {
animation: item-hide 0.5s 0.9s linear reverse;
}
li:nth-of-type(3) {
animation: item-hide 0.5s 0.7s linear reverse;
}
li:nth-of-type(4) {
animation: item-hide 0.5s 0.5s linear reverse;
}
}
Heres a JSFiddle Example

Related

How to repeat fade-in effect on element?

Update
Adding a delay solved my problem:
setTimeout(() => price.classList.add("fade-it"), 100);
but this answer also worked for me
Original question
I have a fade-in effect on background color that should be repeated from time to time initiated by me.
I'm using pure CSS:
<style>
#-webkit-keyframes yellow-fade {
from {
background: #f96;
}
to {
background: #fff;
}
}
#-moz-keyframes yellow-fade {
from {
background: #f96;
}
to {
background: #fff;
}
}
#keyframes yellow-fade {
from {
background: #f96;
}
to {
background: #fff;
}
}
.fade-it {
-webkit-animation: yellow-fade 1s ease-in-out 0s;
-moz-animation: yellow-fade 1s ease-in-out 0s;
-o-animation: yellow-fade 1s ease-in-out 0s;
animation: yellow-fade 1s ease-in-out 0s;
}
</style>
How do I restart this effect after it's already played once?
The code I have is not working after the first time:
var price = document.getElementById("price");
if (price.classList.contains("fade-it")) {
price.classList.remove("fade-it");
}
price.classList.add("fade-it");
You can accomplish this by removing the node from the DOM then adding it back. The append function does exactly that, just append the element to it's parentNode. Give the element it's own wrapper to be the parentNode that way it will not be reordered with other sibling-elements.
const price = document.getElementById("price");
const btn = document.getElementById("fade-price");
const fade = function() {
if (price.classList.contains("fade-it")) {
price.classList.remove("fade-it");
}
price.classList.add("fade-it");
}
document.addEventListener("DOMContentLoaded", function() {
fade()
});
btn.addEventListener("click", function() {
price.parentElement.append(price)
});
#-webkit-keyframes yellow-fade {
from {
background: #f96;
}
to {
background: #fff;
}
}
#-moz-keyframes yellow-fade {
from {
background: #f96;
}
to {
background: #fff;
}
}
#keyframes yellow-fade {
from {
background: #f96;
}
to {
background: #fff;
}
}
.fade-it {
-webkit-animation: yellow-fade 1s ease-in-out 0s;
-moz-animation: yellow-fade 1s ease-in-out 0s;
-o-animation: yellow-fade 1s ease-in-out 0s;
animation: yellow-fade 1s ease-in-out 0s;
}
<div>
<h4 id="price">$9.99</h4>
</div>
<button id="fade-price">
fade
</button>

How to apply transition on transform translateX

How I can apply a transition on transform: translateX CSS property in Vue?
I've tried in this way but it doesn't work, I want to have a smooth slide in/out effect when the menu is opened or closed. I'm using Vue and Bootstrap.
<transition name="slide">
<div class="collapse navbar-collapse position-fixed" :class="{ 'show': isVisible }" ref="menuLinks">
<ul class="navbar-nav ml-auto">
<li class="nav-item" v-for="(item, index) in items" :key="index">
<a class="nav-link" :href="item.link">{{ item.title }}</a>
</li>
</ul>
</div>
</transition>
//CSS
.navbar-collapse {
top: 0;
left: 0;
height: 100vh;
width: 25%;
background:white;
right: 0;
padding: 2em;
transition: transform 1s linear;
}
.slide-enter-active, .slide-enter {
//to do animation soft
transition: transform 1s linear;
animation: slideIn;
animation-duration: 1s;
}
.slide-leave-active, .slide-leave-to {
transition: transform 1s linear;
animation: slideOut;
animation-duration: 1s;
}
#keyframes slideIn {
from {
transform: transaletX(-100%);
}
to {
transform: transaletX(0);
}
}
#keyframes slideOut {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}
UPDATE
I've removed the transition from .slide-leave-active as suggested but nothing change
.slide-enter-active, .slide-enter {
transition: transform 1s ease-in-out;
animation: slideIn;
animation-duration: 1s;
}
.slide-leave-active, .slide-leave-to {
animation: slideOut;
animation-duration: 1s;
}

Why does my div only animate when i add an attribute of isopen=true but not when i change the value to false

When I click on a button I want my div to animate. It seems only the show animation is working, but not the hide. The hide animation doesn't work at all even though the attribute values change.
$("#divShow").click(function() {
$('.parent').attr('isopen', 'true');
});
$("#divHide").click(function() {
$('.parent').attr('isopen', 'false');
});
.parent {
display: none; //hidden by default
width: 40px;
height: 40px;
background: blue;
}
#keyframes show {
50% {
transform: scale(1.03);
}
}
#keyframes hide {
50% {
transform: scale(0.97);
}
100% {
opacity: 0;
transform: scale(0.90);
}
}
[isopen="true"] {
display: block;
-webkit-animation: show .3s;
-moz-animation: show .3s;
-ms-animation: show .3s;
animation: show .3s;
}
[isopen="false"] {
-webkit-animation: hide .3s;
-moz-animation: hide .3s;
-ms-animation: hide .3s;
animation: hide .3s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="divShow">Show</button>
<button id="divHide">Hide</button>
<div class="parent">
</div>
I think I got it working as you wanted. See here code snippet below.
Your show class has display block but when you remove it it gets right back to none. Just add the display none at the end of your hide animation.
Like this:
#keyframes hide {
50% {
transform: scale(0.97);
}
100% {
opacity: 0;
transform: scale(0.90);
display: none;
}
}
[isopen="false"] {
display: block;
animation: hide .3s forwards;
}
Code snippet:
$("#divShow").click(function() {
$('.parent').attr('isopen', 'true');
});
$("#divHide").click(function() {
$('.parent').attr('isopen', 'false');
});
.parent {
display: none; //hidden by default
width: 40px;
height: 40px;
background: blue;
}
#keyframes show {
50% {
transform: scale(1.03);
}
}
#keyframes hide {
50% {
transform: scale(0.97);
}
100% {
opacity: 0;
transform: scale(0.90);
display: none;
}
}
[isopen="true"] {
display: block;
-webkit-animation: show .3s;
-moz-animation: show .3s;
-ms-animation: show .3s;
animation: show .3s;
}
[isopen="false"] {
display: block;
-webkit-animation: hide .3s forwards;
-moz-animation: hide .3s forwards;
-ms-animation: hide .3s forwards;
animation: hide .3s forwards;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="divShow">Show</button>
<button id="divHide">Hide</button>
<div class="parent">
</div>
With the help of this answer: https://stackoverflow.com/a/15407098/2181514
you can add forwards to your animations so that they keep the last (100%) keyframe.
Add display:block to [isopen=false] to ensure it doesn't hide immediately then:
animation: hide .3s forwards;
Updated snippet:
$("#divShow").click(function() {
$('.parent').attr('isopen', 'true');
});
$("#divHide").click(function() {
$('.parent').attr('isopen', 'false');
});
.parent {
display: none;
width: 40px;
height: 40px;
background: blue;
}
#keyframes show {
50% {
transform: scale(1.03);
}
}
#keyframes hide {
50% {
transform: scale(0.97);
}
100% {
opacity: 0;
transform: scale(0.90);
}
}
[isopen="true"] {
display: block;
-webkit-animation: show .3s;
-moz-animation: show .3s;
-ms-animation: show .3s;
animation: show .3s;
}
[isopen="false"] {
display: block;
-webkit-animation: hide .3s forwards;
-moz-animation: hide .3s forwards;
-ms-animation: hide .3s forwards;
animation: hide .3s forwards;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="divShow">Show</button>
<button id="divHide">Hide</button>
<div class="parent">
</div>
Can be done simply, efficiently with less line of code using transition
$("#divShow").click(function() {
$('.parent').addClass('show');
});
$("#divHide").click(function() {
$('.parent').removeClass('show');
});
.parent {
width: 40px;
height: 40px;background: blue;
transform: scale(0.97);
transition: all 0.3s;
opacity:0;
}
.show {
opacity:1;
transform: scale(1.03);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="divShow">Show</button>
<button id="divHide">Hide</button>
<div class="parent">
</div>

Making animation on event trigger with Javascript and CSS

I am new using javascript and CSS and am currently trying to make a small animation that is triggered at event call. The animation is simple, and only changes the transparancy of an image. My problem is that that the animation only works every other time the function is called.
A function called "pulse()" is called every time I want the animation to happen.
<script>
function pulse() {
$('.transform').toggleClass('transform-active');
}
</script>
The CSS looks like this:
.lock-image {
}
.transform {
-webkit-transition: all 1s ease-in-out;
-moz-transition: all 1s ease-in-out;
-o-transition: all 1s ease-in-out;
-ms-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
}
.transform-active {
/*animation-delay: 2s;*/
animation-iteration-count: 1;
animation: pulse 0.5s;
animation-direction: alternate;
}
#keyframes pulse {
0% {
opacity: 1;
}
50%{
opacity: 0.3;
}
100% {
opacity: 1;
}
}
The image on which the animation is done is done like this;
<div class="lock-image transform">
<img id="myImage" src="pic_locked.png" class="img-responsive " style="display:inline" alt="Lock" width="100" height="80">
</div>
How can I change the code so the animation happens every time the function pulse() is called?
You can add an event handler to handle when the animation ends to remove the class. For the purpose of the example, I've changed the image to a red div
function pulse() {
$('.transform').addClass('transform-active');
}
$('.transform').on('webkitAnimationEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function() {
$(this).removeClass('transform-active');
})
#myImage {
display: block;
background-color: red;
width: 100px;
height: 80px;
}
.transform {
-webkit-transition: all 1s ease-in-out;
-moz-transition: all 1s ease-in-out;
-o-transition: all 1s ease-in-out;
-ms-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
}
.transform-active {
/*animation-delay: 2s;*/
animation-iteration-count: 1;
animation: pulse 0.5s;
animation-direction: alternate;
}
#keyframes pulse {
0% {
opacity: 1;
}
50% {
opacity: 0.3;
}
100% {
opacity: 1;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="lock-image transform">
<div id="myImage"></div>
</div>
<br/>
<button type="button" onclick="pulse()">Pulse</button>

Jquery dlmenu animation is not smooth

I have created multilevel navigation menu using jquery dlmenu plugin v1.0.2 demo2.
Everything works fine, except CSS3 menu navigation is not smooth as jQuery left/right slide functionality is.
Is there any solution to resolve this issue without changing plugin?
/* Animation classes for moving out and in */
.dl-menu.dl-animate-out-2 {
-webkit-animation: MenuAnimOut2 0.3s ease-in-out forwards;
-moz-animation: MenuAnimOut2 0.3s ease-in-out forwards;
animation: MenuAnimOut2 0.3s ease-in-out forwards;
}
#-webkit-keyframes MenuAnimOut2 {
100% {
-webkit-transform: translateX(-100%);
opacity: 0;
}
}
#-moz-keyframes MenuAnimOut2 {
100% {
-moz-transform: translateX(-100%);
opacity: 0;
}
}
#keyframes MenuAnimOut2 {
100% {
transform: translateX(-100%);
opacity: 0;
}
}
.dl-menu.dl-animate-in-2 {
-webkit-animation: MenuAnimIn2 0.3s ease-in-out forwards;
-moz-animation: MenuAnimIn2 0.3s ease-in-out forwards;
animation: MenuAnimIn2 0.3s ease-in-out forwards;
}
#-webkit-keyframes MenuAnimIn2 {
0% {
-webkit-transform: translateX(-100%);
opacity: 0;
}
100% {
-webkit-transform: translateX(0px);
opacity: 1;
}
}
#-moz-keyframes MenuAnimIn2 {
0% {
-moz-transform: translateX(-100%);
opacity: 0;
}
100% {
-moz-transform: translateX(0px);
opacity: 1;
}
}
#keyframes MenuAnimIn2 {
0% {
transform: translateX(-100%);
opacity: 0;
}
100% {
transform: translateX(0px);
opacity: 1;
}
}
You have to use the plugin like this : with animationClasses "in" and "out" not "classin" and "classout"
$(function() {
$( '#dl-menu' ).dlmenu({
animationClasses : { in : 'dl-animate-in-2', out : 'dl-animate-out-2' }
});
});

Categories