Reverse a CSS animation without jquery - javascript

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>

Related

How do transitions work when fading in and out using css classes and javascript

I am trying to find out how transitions work. I am trying to make a thumbs up appear using a fade in fade out transition for a recycling simulator program, however, I do not know how understand how transitions work.
Here is a snippet of my html
<div class="thumbs-up-bg">
<i class="fas fa-thumbs-up" id="thumbs-up"></i>
</div>
<div class="thumbs-down-bg">
<i class="fas fa-thumbs-down" id="thumbs-down"></i>
</div>
Here is the CSS
.thumbs-up-bg {
position: absolute;
visibility: hidden;
background-color: green;
display: inline-block;
border-radius: 50%;
width: 60px;
height: 60px;
text-align: center;
opacity: 0;
transition: opacity 0.1s ease-in-out;
}
#thumbs-up-bg.visible {
opacity: 1;
}
#thumbs-up {
font-size: 50px;
color: white;
}
.thumbs-down-bg {
position: absolute;
visibility: hidden;
background-color: red;
display: inline-block;
border-radius: 50%;
width: 60px;
height: 60px;
text-align: center;
opacity: 0;
transition: opacity 0.1s ease-in-out;
}
#thumbs-down {
font-size: 50px;
color: white;
}
.visible {
visibility: visible;
opacity: 1;
transition: opacity 2s linear;
}
.hidden {
opacity: 0;
transition: visibility 5s, opacity 2s linear;
}
Are transitions supposed to be set on the selector that is going to be changed? Is there a simpler way to complete this task?
Here is the Javascript
if (drop === trashDropZone){
if(!isRecyclable(draggable)){
alert("Success, it is garbage");
thumbsUp.classList.toggle("visible");
setTimeout(() =>{
thumbsUp.classList.toggle("visible");
thumbsUp.classList.toggle("hidden");
}, 1000);
makeInvisible(draggable);
} else{
//show thumbs down
alert("Thumbs down");
thumbsDown.classList.toggle("visible");
setTimeout(() =>{
thumbsDown.classList.toggle("visible");
thumbsDown.classList.toggle("hidden");
}, 1000);

How to use CSS animation-delay and transform? [duplicate]

This question already has answers here:
How can I delay the start of a CSS animation?
(3 answers)
Maintaining the final state at end of a CSS animation
(5 answers)
Closed 2 years ago.
How can I use setinterval() for css animation?
For example, in the example below, I want the div to come with animation after 3000ms. How do I do this?
Can I get it starting from bottom 0, like the price segment that changes when I choose the minute and day as on this page?
<div><span>$</span>2.000</div>
jsfiddle example
div {
font-size: 42px;
position: relative;
animation: mymove 0.3s;
animation-timing-function: ease-in-out;
}
div span{
font-size: 24px;
padding-right: 5px;
}
#keyframes mymove {
0% {
bottom: -70px;
}
100% {
bottom: 0px;
}
}
Set an animation-delay, together with animation-fill-mode:forwards to prevent the div from reverting to the initial state when the animation has finished. You can use opacity to control when to show the element (I've used a dark body background here so that your white text is visible):
body {
background: #333;
color: #fff;
}
.wrapper {
overflow: hidden;
}
.wrapper div {
font-size: 42px;
position: relative;
animation: mymove 0.3s;
animation-timing-function: ease-in-out;
animation-delay: 3s;
animation-fill-mode: forwards;
opacity: 0;
}
.wrapper div span {
font-size: 24px;
padding-right: 5px;
}
#keyframes mymove {
0% {
opacity: 1;
display: block;
transform: translateY(-70px);
}
100% {
opacity: 1;
display: block;
transform: translateY(0px);
}
}
<div class="wrapper">
<div><span>$</span>2.000</div>
</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>

Multiple CSS animations: How to avoid re-triggering one of them?

I am trying to build an animated menu for mobile apps similar to Pinterest's radial menu. I have managed to get the behaviour to where I want it except for one minor detail: when the menu opens, the items shoot out as I want them to, and when you hover on them, they transform as I want them to. problem is, after the cursor leaves the items, they re-trigger their original animation, instead of just returning to their previous state. I realise this is a problem to do with the class being used for the animation and I have tried a number of solutions, including deleting the class and adding a new one .onmouseover() and changing animation running state on hover/mousover. I am probably missing something simple and idiotic, but I just cannot see it. can anybody help?
The following code is just the way I had it before trying to implement solutions.
HTML:
<!--Footer-->
<div class="footer">
<!--RADIAL NAV MENU-->
<div id="navContainer">
<!--Buttons-->
<div id="workouts" class="sml smlOne">Go there</div>
<div id="home" class="sml smlTwo">Go here</div>
<div id="profile" class="sml smlThree">Go somewhere</div>
<!--Burger-->
<div class="burger-menu">
<div id="top" class="bar barTop"></div>
<div id="middle" class="bar barMid"></div>
<div id="bottom" class="bar barBot"></div>
</div>
</div>
</div>
CSS:
.footer
{
position: fixed;
bottom: 0%;
width: 100%;
height: 50px;
background-color: #d36363;
box-shadow: 0px -6px 6px #888888;
z-index: +2;
}
/* Burger menu section */
#navContainer
{
text-align: center;
font-size: 10px;
}
.burger-menu
{
position: relative;
margin: auto;
height: 100%;
width: 50px;
}
.bar
{
height: 6px;
width: 100%;
background-color: white;
}
#top
{
position: relative;
top: 5px;
}
#middle
{
position: relative;
top: 15px;
}
#bottom
{
position: relative;
top: 25px;
}
.barTop, .barMid, .barBot
{
-webkit-transition: all 0.1s ease;
-moz-transition: all 0.1s ease;
-o-transition: all 0.1s ease;
-ms-transition: all 0.1s ease;
transition: all 0.1s ease;
}
.barTopOn
{
transform: rotate(45deg) translateY(12px) translateX(11px);
}
.barMidOn
{
opacity: 0;
}
.barBotOn
{
transform: rotate(-45deg) translateY(-12px) translateX(11px);
}
/* Navigation buttons section */
#navContainer
{
position: relative;
margin: auto;
width: 50px;
}
.sml
{
border: 2px solid #58a7dd;
height: 50px;
width: 50px;
border-radius: 50%;
background-color: white;
box-shadow: 6px 6px 6px #888888;
transform: scale(0);
}
#workouts
{
position: absolute;
bottom: 10px;
left: -60px;
}
#home
{
position: absolute;
bottom: 50px;
}
#profile
{
position: absolute;
bottom: 10px;
left: 60px;
}
.smlOnOne
{
animation: pop, slideOne 0.1s ease-in;
animation-fill-mode: forwards;
}
.smlOnTwo
{
animation: pop, slideTwo 0.1s ease-in;
animation-fill-mode: forwards;
}
.smlOnThree
{
animation: pop, slideThree 0.1s ease-in;
animation-fill-mode: forwards;
}
.smlOnOne:hover
{
background-color: red;
border: none;
box-shadow: 6px 10px 18px #686868;
animation: whopL 0.2s;
animation-fill-mode: forwards;
}
.smlOnTwo:hover
{
background-color: red;
border: none;
box-shadow: 6px 10px 18px #686868;
animation: whopC 0.2s;
animation-fill-mode: forwards;
}
.smlOnThree:hover
{
background-color: red;
border: none;
box-shadow: 6px 10px 18px #686868;
animation: whopR 0.2s;
animation-fill-mode: forwards;
}
#keyframes pop
{
100%
{
transform: scale(1,1);
}
}
#keyframes slideOne
{
0%
{
bottom: -20px;
left: 0px;
}
100%
{
bottom: 10px;
left: -60px;
}
}
#keyframes slideTwo
{
0%
{
bottom: -20px;
}
100%
{
bottom: 50px;
}
}
#keyframes slideThree
{
0%
{
bottom: -20px;
left: 0px;
}
100%
{
bottom: 10px;
left: 60px;
}
}
#keyframes whopL
{
0%
{
transform: scale(1,1) translateY(0px) translateX(0px);
}
100%
{
transform: scale(1.5) translateY(-10px) translateX(-10px);
}
}
#keyframes whopC
{
0%
{
transform: scale(1,1) translateY(0px) translateX(0px);
}
100%
{
transform: scale(1.5) translateY(-10px);
}
}
#keyframes whopR
{
0%
{
transform: scale(1,1) translateY(0px) translateX(0px);
}
100%
{
transform: scale(1.5) translateY(-10px) translateX(10px);
}
}
JS/jQuery:
$(".burger-menu").click(function()
{
$(".barTop").toggleClass("barTopOn");
$(".barMid").toggleClass("barMidOn");
$(".barBot").toggleClass("barBotOn");
$(".smlOne").toggleClass("smlOnOne");
$(".smlTwo").toggleClass("smlOnTwo");
$(".smlThree").toggleClass("smlOnThree");
});
Here is a working demo:
https://codepen.io/BGGrieco/pen/NgjxXq
You have an element that is a set of #-webkit-keyframes to animate in. On hamburger-menu click, these keyframes run, and that works well.
Next, you have a second set of #-webkit-keyframes on hover, so on hover works well too.
However, the instant the mouse is away from the element, the first (intro) set of keyframes gets run again. You don't want it to run after it first runs.
Here is what I was able to accomplish:
https://codepen.io/CapySloth/pen/RgxKEb
<div id="workouts" class="sml smlOne">
<div class="test1">
Go there
</div>
</div>
Instead of stacking classes which contain keyframe animations onto the one ".sml" class, I have split the task between two elements. ".sml" now acts as a wrapper which takes care of the "hamburger-menu open" animation and "test1 a" takes care of the "whop" animation.
If you can find a way to hide/show parents of the "test1 a/test2 a/test3 a" then you will have what you want.
You can use .stop() before your .toggleClass.
$("#example").stop().toggleClass("class");

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