How can I get a CSS animation to work in reverse? - javascript

I am trying to animate my menu. The menu open animation works fine, but I can't get the menu close animation to work.
The menu opens fine, but I don't know how to make it close with the MenuClose settings.
function showMenu() {
const el = document.getElementById("MenuContainer");
el.classList.toggle('MenuOpen');
}
#MenuContainer {
height: 0px;
left: 10px;
overflow: hidden;
padding: 5px 0px 0px 0px;
position: relative;
top: 20px;
width: 0px;
}
.MenuOpen {
animation-direction: normal;
animation-duration: 4s;
animation-fill-mode: forwards;
animation-name: Menu;
}
.MenuClose {
animation-direction: reverse;
animation-duration: 2s;
animation-fill-mode: forwards;
animation-name: Menu;
}
#keyframes Menu {
from {
height: 0px;
width: 0px;
}
to {
height: 100px;
width: 300px;
}
}
<input id="MenuButton" type="button" value="Menu" onclick="showMenu();" title="Menu" />
<div id="MenuContainer"></div>

2 main points:
you toggle MenuOpen with... nothing, it puts menuopen and remove it
better to have open animation and close animation, eas
function showMenu() {
const el = document.getElementById("MenuContainer");
if (el.classList.contains('MenuOpen')) {
el.classList.add('MenuClose');
el.classList.remove('MenuOpen');
} else {
el.classList.add('MenuOpen');
el.classList.remove('MenuClose');
}
}
#MenuContainer {
height: 0px;
left: 10px;
overflow: hidden;
padding: 5px 0px 0px 0px;
position: relative;
top: 20px;
width: 0px;
background-color: #3388ff;
}
.MenuOpen {
animation-duration: 4s;
animation-fill-mode: forwards;
animation-name: MenuOpen;
}
.MenuClose {
animation-duration: 2s;
animation-fill-mode: forwards;
animation-name: MenuClose;
}
#keyframes MenuOpen {
from {
height: 0px;
width: 0px;
}
to {
height: 100px;
width: 300px;
}
}
#keyframes MenuClose {
from {
height: 100px;
width: 300px;
}
to {
height: 0px;
width: 0px;
}
}
<input id="MenuButton" type="button" value="Menu" onclick="showMenu();" title="Menu" />
<div id="MenuContainer"></div>
ier to control

You can use if else statement and replace function to toggle the open close animation.
//Get the menu container
const el = document.getElementById("MenuContainer");
// Function to toggle the menu open/close animation
function showMenu() {
// Check if the menu container has the 'MenuOpen' class
if (el.classList.contains('MenuOpen')) {
// Replace the 'MenuOpen' class with 'MenuClose'
el.classList.replace('MenuOpen', 'MenuClose');
} else {
// Add the 'MenuOpen' class to the menu container
el.classList.add('MenuOpen');
}
}
Hope this will help. This is just one solution of many ways.

Related

Unable to make a smooth transition in background color when scroll event is triggered

I am trying to to create a fixed header for one of my projects using react. The background color of the Header should be transparent when the web page is opened but on scrolling it down, it should change its color to black. I have managed to make the transition smooth while changing the background color from transparent to black (when I scroll down) however, I am unable to make the transition smooth when the background color changes from black to transparent (when I scroll back up).
Here is my Code :
import React from 'react';
import Navbar from '../Navbar/Navbar.js';
import logo from '../images/nsut_logo.png';
class Header extends React.Component {
constructor() {
super();
this.state = {
header: false
};
this.handleScroll = this.handleScroll.bind(this);
}
componentDidMount(){
window.addEventListener("scroll", this.handleScroll);
}
handleScroll(event) {
if (window.pageYOffset > 0) {
this.setState({ header: true });
}
else{
this.setState({ header: false });
}
}
render() {
return (
<header onScroll={this.handleScroll}>
<div className={this.state.header ? "Header-Site-Title-Active" : "Header-Site-Title"}>
<img className = "Header-logo" src={logo} />
<div className="Department-Name">
<h1 >
<b>Department Of Computer Science And Engineering</b>
<br/>
</h1>
<h3>
Netaji Subhas University of Technology
</h3>
</div>
<Navbar />
</div>
</header>
);
}
}
export default Header;
Here is my CSS File:
header{
top: 0;
padding-bottom: 1%;
position: fixed;
z-index: 5;
height: 17vh;
}
#keyframes bgChangeDown {
0% {background-color: none;}
100% {background-color: black;}
}
#keyframes bgChangeUp {
0% {background-color: inherit;}
100% {background-color: none;}
}
.Handle-Site-Title {
height: 100px;
width: 100vw;
top: 0;
animation-name: bgChangeUp;
animation-duration: 2s;
animation-iteration-count: 1;
transition: ease-in 1.5s;
animation-fill-mode: forwards;
}
.Header-Site-Title-Active {
height: 100px;
width: 100vw;
top: 0;
animation-name: bgChangeDown;
animation-duration: 2s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
transition: ease-in 1.5s;
}
.Header-logo{
height:100px;
padding: 5px 10px 0 5px;
margin: 0;
display: inline;
float: left;
}
.Department-Name{
margin: 0;
margin-bottom: 5px;
height: 100px;
float: left;
display: inline;
color: white;
}
.Department-Name h3{
margin-bottom: 15px;
margin-top: -17px
}
.hamburger{
position: fixed;
cursor: pointer;
margin: 5px;
right: 5%;
top: 5%;
}
.line{
width: 30px;
height: 3px;
background: white;
margin: 5px;
}
.sidenav {
height: 100%; /* 100% Full-height */
width: 0; /* 0 width - change this with JavaScript */
position: fixed; /* Stay in place */
z-index: 1; /* Stay on top */
top: 0; /* Stay at the top */
right: 0;
background-color: black; /* Black*/
overflow-x: hidden; /* Disable horizontal scroll */
padding-top: 60px; /* Place content 60px from the top */
transition: 0.5s; /* 0.5 second transition effect to slide in the sidenav */
}
.sidenav-active {
height: 100%; /* 100% Full-height */
width: 250px; /* 0 width - change this with JavaScript */
position: fixed; /* Stay in place */
z-index: 1; /* Stay on top */
top: 0; /* Stay at the top */
right: 0;
background-color: black; /* Black*/
overflow-x: hidden; /* Disable horizontal scroll */
padding-top: 60px; /* Place content 60px from the top */
transition: 0.5s; /* 0.5 second transition effect to slide in the sidenav */
}
/* The navigation menu links */
.sidenav a, .sidenav-active a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: white;
display: block;
transition: 0.3s;
}
/* When you mouse over the navigation links, change their color */
.sidenav a:hover, .sidenav-active a:hover {
color: #f1f1f1;
}
/* Position and style the close button (top right corner) */
.sidenav .closebtn, .sidenav-active .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
#media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;}
}
I am still learning React so feel free to suggest a new approach as well.
The classes that you're applying in your React component are Header-Site-Title-Active and Header-Site-Title but in your CSS your bgChangeUp animation is assigned to the Handle-Site-Title class, not Header-Site-Title:
.Handle-Site-Title {
height: 100px;
width: 100vw;
top: 0;
animation-name: bgChangeUp;
animation-duration: 2s;
animation-iteration-count: 1;
transition: ease-in 1.5s;
animation-fill-mode: forwards;
}
.Header-Site-Title-Active {
height: 100px;
width: 100vw;
top: 0;
animation-name: bgChangeDown;
animation-duration: 2s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
transition: ease-in 1.5s;
}
Further to this, this effect may be more easily achieved using CSS transitions:
.Header-Site-Title {
...
background-color: transparent;
transition: background-color ease-in 1.5s;
...
}
.Header-Site-Title-Active {
...
background-color: rgba(0,0,0,black);
...
}

Reverse a CSS animation without jquery

I'm making a dropdown menu that should slide into view on click. I want to make it slide back up on a second click, but have been struggling to figure out how to do so. Most of the answers I've found online involve jQuery, but I am hoping to accomplish this with vanilla js.
My CSS:
.post-more-dropdown {
background-color: #f8f9fa;
display: block;
position: absolute;
right: 0px;
top: 60px;
min-width: 80px;
animation-name: dropdown;
animation-play-state: paused;
animation-fill-mode: backwards;
animation-duration: 0.7s;
a {
display: block;
padding-left: 10px;
padding-top: 10px;
}
a:hover {
background-color: #555555;
color: white;
cursor: pointer;
}
}
#keyframes dropdown {
0% {
max-height: 0px;
opacity: 0;
}
100% {
max-height: 200px;
opacity: 1;
}
}
My javascript:
function post_more_dropdown(post_id) {
dropdown = document.querySelector(`#post-more-dropdown-${post_id}`);
dropdown.style.animationPlayState = "running";
}
This works perfectly to get the dropdown to run on click, but I'm struggling to figure out how to reverse it on the second click. I was thinking I could create a new #keyframes dropdown-reverse animation and add it to the class, but then I realized I can't control two animations under one class with JS. I was thinking I could also create two different classes and add/remove those classes with JS along with controlling two different animations, but I feel like there's got to be a more elegant solution that I'm missing.
I have a feeling that animation-direction is going to be part of the answer, but I haven't quite figured out how that will work for this.
Use the following CSS, change class using JavaScript.
function post_more_dropdown(post_id) {
dropdown = document.querySelector(`#post-more-dropdown-${post_id}`);
if (dropdown.classList.contains('dropdown-animate-forward')) {
dropdown.classList.add('dropdown-animate-backward');
dropdown.classList.remove('dropdown-animate-forward');
} else {
dropdown.classList.add('dropdown-animate-forward');
dropdown.classList.remove('dropdown-animate-backward');
}
}
setInterval(function() {
post_more_dropdown(1)
}, 1000);
.post-more-dropdown {
background-color: #f8f9fa;
display: block;
position: absolute;
right: 0px;
top: 60px;
min-width: 80px;
a {
display: block;
padding-left: 10px;
padding-top: 10px;
}
a:hover {
background-color: #555555;
color: white;
cursor: pointer;
}
}
/* forward animation */
.dropdown-animate-forward {
animation-name: dropdownForward;
animation-fill-mode: backwards;
animation-duration: 0.7s;
}
#keyframes dropdownForward {
0% {
max-height: 0px;
opacity: 0;
}
100% {
max-height: 200px;
opacity: 1;
}
}
/* backward animation */
.dropdown-animate-backward {
animation-name: dropdownBackward;
animation-fill-mode: forward;
animation-duration: 0.7s;
}
#keyframes dropdownBackward {
0% {
max-height: 200px;
opacity: 1;
}
100% {
max-height: 0px;
opacity: 0;
}
}
<div id="post-more-dropdown-1" class="post-more-dropdown">Post more</div>

Trigger CSS Animation on Click via javascript

I have a simple hamburger icon and I want to trigger CSS animation on click via pure javascript(no jquery please). I am doing this by adding and removing a class on hamburger icon when I add the class the CSS animation is happening however when I remove the class the animation is not happening, the hamburger line is coming back abruptly without animating. Basically I want the animation to reverse and come back to original position.
Here is the code:
var hamburgerMenu = document.querySelector('.hamburger-menu');
hamburgerMenu.addEventListener('click', function() {
var hamburgerMenuSpan2 = document.querySelector('.hamburger-second');
hamburgerMenuSpan2.classList.toggle('hamburger-line-2');
});
.hamburger-menu {
position: absolute;
top: 20px;
right: 20px;
}
.hamburger-line-2 {
animation-name: animate;
animation-duration: 3s;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
animation-direction: alternate;
}
#keyframes animate {
0% {
width: 40px;
}
100% {
width: 0px;
}
}
.hamburger-menu span {
display: block;
width: 40px;
height: 2px;
background: black;
margin: 10px 0px;
}
<div class="hamburger-menu">
<span class="hamburger-line-1"></span>
<span class="hamburger-second"></span>
<span class="hamburger-line-3"></span>
</div>
Basically I want the hamburger icon line to become 0px width on click with duration and then whenever user clicks again I want the hamburger icon line to become original width starting from 0.
A bit ugly, because of the extra class needed, but it works:
var hamburgerMenu = document.querySelector('.hamburger-menu');
hamburgerMenu.addEventListener('click', function() {
var hamburgerMenuSpan2 = document.querySelector('.hamburger-second');
if (hamburgerMenuSpan2.classList.contains("animate-out")) {
hamburgerMenuSpan2.classList.remove("animate-out");
hamburgerMenuSpan2.classList.add("animate-in");
} else {
hamburgerMenuSpan2.classList.add("animate-out");
hamburgerMenuSpan2.classList.remove("animate-in");
}
});
.hamburger-menu {
position: absolute;
top: 20px;
right: 20px;
}
.hamburger-line-2 {
animation-duration: 3s;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
animation-direction: alternate;
}
.animate-out {
animation-name: animate-out;
}
.animate-in {
animation-name: animate-in;
}
#keyframes animate-out {
0% {
width: 40px;
}
100% {
width: 0px;
}
}
#keyframes animate-in {
0% {
width: 0px;
}
100% {
width: 40px;
}
}
.hamburger-menu span {
display: block;
width: 40px;
height: 2px;
background: black;
margin: 10px 0px;
}
<div class="hamburger-menu">
<span class="hamburger-line-1"></span>
<span class="hamburger-second hamburger-line-2"></span>
<span class="hamburger-line-3"></span>
</div>
If you are free to use CSS transition, then this could be a great solution.
var hamburgerMenu = document.querySelector('.hamburger-menu');
hamburgerMenu.addEventListener('click', function() {
var hamburgerMenuSpan2 = document.querySelector('.hamburger-second');
if (hamburgerMenuSpan2.classList.contains('low-width')) {
hamburgerMenuSpan2.classList.remove('low-width');
} else {
hamburgerMenuSpan2.classList.add('low-width');
}
});
.hamburger-menu {
position: absolute;
top: 20px;
right: 20px;
}
.hamburger-second {
transition: width 3s ease-in-out;
}
.low-width {
width: 0px !important;
}
.hamburger-menu span {
display: block;
width: 40px;
height: 2px;
background: black;
margin: 10px 0px;
}
<div class="hamburger-menu">
<span class="hamburger-line-1"></span>
<span class="hamburger-second"></span>
<span class="hamburger-line-3"></span>
</div>

How to stop css animation in current position on hover?

I have a div inside which moves another div. I need to stop .block at the current position when I hover on .container. How to do it?
HTML:
<div class="container">
<div class="block"></div>
</div>
CSS:
.container {
width: 200px;
height: 100px;
padding: 10px;
border: 1px solid #000;
position: relative;
}
.block {
width: 100px;
height: 100px;
background: red;
position: absolute;
animation: move 2s linear infinite;
}
#keyframes move {
0% { left: 10px; }
25% { left: 50px; }
50% { left: 100px; }
75% { left: 50px; }
100% { left: 10px; }
}
DEMO
You can add
.block:hover
{
animation-play-state: paused;
}
to pause the animation when you hover over it.
https://developer.mozilla.org/en-US/docs/Web/CSS/animation-play-state
You can pause animation when hover on .container. Consider following css:
.container:hover .block{
animation-play-state: paused;
}
DEMO
CSS:
.container:hover > .block {
-webkit-animation-play-state:paused;
-moz-animation-play-state:paused;
-o-animation-play-state:paused;
animation-play-state:paused;
}
JS:
var node = document.getElementsByClassName("block")[0];
node.addEventListener('mouseenter', function(evt) {
evt.currentTarget.style.webkitAnimationPlayState = 'paused';
});
node.addEventListener('mouseleave', function(evt) {
evt.target.style.webkitAnimationPlayState = 'running';
});

Animation didn't work properly when click the button in menu [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Here is my jsfiddle: https://jsfiddle.net/n1ssf5up/5/
I took the source code from this link: http://codepen.io/MrBambule/pen/jIseg
I need to change the code for getting small size button.
It works fine, when i increase the font-size, as 0.7em to 1.7em for the list.
css:
.button {
position: relative;
width: 50px;
height: 50px;
border: 1px solid;
border-radius: 50%;
background: #2E3F47;
z-index: 10;
}
.line {
background: #ccc;
width: 15px;
height: 5px;
margin: 2px auto;
}
.line__first {
margin-top: 15px;
}
.menu {
z-index: 1;
float: left;
width: 100%;
}
/* for the list to be horizontaly centered */
.table {
display: table;
margin: 0 auto;
}
.menu__list {
width: 100%;
margin-left:-110px;
margin-top:-10px;
}
/* Animation keyframes for the drop down */
#keyframes drop {
from {
top: 0px;
}
70% {
top: 85px;
animation-timing-function: ease-in;
}
to {
top: 70px;
animation-timing-function: ease-out;
}
}
#-webkit-keyframes drop {
from {
top: 0px;
}
70% {
top: 85px;
-webkit-animation-timing-function: ease-in;
}
to {
top: 70px;
-webkit-animation-timing-function: ease-out;
}
}
li {
position: relative;
list-style: none;
padding-bottom: 0px;
top: 0px;
}
li a {
text-decoration: none;
color: grey;
text-align: center;
font-size: 0.7em;
font-family: 'Open Sans', sans-serif;
}
.menu__list__item {
opacity: 0;
}
/*Animation classes to add to list-items that should be animated*/
.list--animation, .list--animation--delay1, .list--animation--delay2 {
animation: drop 0.9s;
-webkit-animation: drop 0.9s;
animation-fill-mode: forwards;
opacity: 1;
-webkit-animation-fill-mode: forwards;
opacity: 1;
}
.list--animation--delay1 {
animation-delay: 0.5s;
-webkit-animation-delay: 0.5s;
}
.list--animation--delay2 {
animation-delay: 1s;
-webkit-animation-delay: 1s;
}
I need same animation and with small size button.
may i know how to do this? thanks in advance.
Try to use this:
.line { background: #ccc;width: 30%;height: 16%;margin: 10% auto;} line__first { margin-top: 15%;}
check out this
demo
You have to add class with delay in jQuery code..
$('.item1').addClass('list--animation');
$('.item2').delay(1000).queue(function(){
$(this).addClass('list--animation--delay1').clearQueue();
});
$('.item3').delay(2000).queue(function(){
$(this).addClass('list--animation--delay2').clearQueue();
});
Change in CSS
.list--animation--delay1 {
animation-delay: 0s;
-webkit-animation-delay: 0s;
}
.list--animation--delay2 {
animation-delay: 0s;
-webkit-animation-delay: 0s;
}

Categories

Resources