What is the best way for me to make my hamburger animation play in reverse?

Having trouble achieving smooth animation effects.

I've designed a burger icon using three divs:

<div class="container">
<div class="burger-contain">
    <div id="line-1" class="line"></div>
    <div id="line-2" class="line"></div>
    <div id="line-3" class="line"></div>
</div>
</div>

I have defined separate keyframes for each line:

.line:first-child {
   animation-name: firstChild;
   transform-origin: 30px 25px;
   animation-duration: 0.5s;
   animation-fill-mode: forwards;
   margin: 10px;
}

Here are the keyframes used:

@keyframes firstChild {
0% {transform: translateY(0);}
50% {transform: translateY(10px);}
100% {transform: rotate(-45deg);}
}

All three lines have slightly different animations. The second line disappears, while the third moves up instead of down.

To achieve the click function, I utilized jQuery to toggle between classes as follows:

$(document).ready(function(){

var line = $(".line");
var burger = $(".burger-contain")
var toggled = false;

burger.click(function(){
   triggerAnimation();
});

function triggerAnimation(){
   if (toggled === false){
   line.removeClass("reverse");
   line.addClass("animate");
   toggled = true;
} else {

   line.removeClass("animate");
   line.addClass("reverse");
   toggled = false; 
}

}


});

To reverse the animation, I intended to use animation-direction: reverse; in my CSS like this:

.line:first-child.reverse {
animation-name: firstChild;
transform-origin: 30px 25px;
animation-duration: 0.5s;
animation-fill-mode: forwards;
margin: 10px;
animation-direction: reverse;
}

This is applied to all three lines. However, an issue arises where the animation stops functioning after the initial run. There seems to be no transition between the states, causing the animation to only work once in both directions - from Burger to Cross and vice versa.

Is there a flaw in my logic or am I misunderstanding the concept behind reversing animations?

Answer №1

Your understanding of the reverse concept may not be entirely accurate.

When an animation is set to play in reverse, it essentially goes back to its end state and starts over again with each cycle. The animation steps are reversed, and even the timing functions change accordingly—like ease-in becoming ease-out.source

In your scenario, adding the 'reverse' attribute after the animation has already concluded will not restart the animation; instead, it will just swap the start and end states.

Let's consider a simple example. On hover, you'll notice a sudden jump in the animation instead of a fluid direction change because we have reversed the entire animation without adjusting the element's position. It's akin to observing a reflection in a mirror:

.box {
  width:50px;
  height:50px;
  background:red;
  animation:change 5s linear forwards;
}

@keyframes change {
  from {transform:translateX(0)}
  to {transform:translateX(300px)}
}

body:hover .box{
   animation-direction:reverse;
}
<div class="box">

</div>

After the animation completes, you can clearly see how the first and last states switch when hovering.


An alternate approach would be using transitions instead of animations, requiring less code for the effect.

Note: I've utilized 'hover,' but this can easily be replaced with a class toggle.

.menu {
  height:50px;
  width:60px;
  position:relative;
  margin:50px;
  background:
    linear-gradient(#000,#000) center/100% 10px no-repeat;
  transition:all 0s 0.5s;
}
.menu:before,
.menu:after{
  content:"";
  position:absolute;
  left:0;
  height:10px;
  width:100%;
  background:#000;
  transition:0.5s 0.5s top,0.5s 0.5s bottom,0.5s transform;
}
.menu:before {
  top:0;
}
.menu:after {
  bottom:0;
}

.menu:hover {
  background-size:0px 0px;
}

.menu:hover:before {
  top:calc(50% - 5px);
  transform:rotate(45deg);
  transition:0.5s top,0.5s 0.5s transform;
}

.menu:hover:after {
  bottom:calc(50% - 5px);
  transform:rotate(-45deg);
  transition:0.5s bottom,0.5s 0.5s transform;
}
<div class="menu">
  
</div>

Answer №2

Here is a working example: https://jsfiddle.net/upnhcw69/38/

The solution involves utilizing 2 animations and switching between them to ensure they are triggered correctly.

Upon the first click, the `firstChild` animation is activated, followed by the activation of the `firstChild2` animation upon the second click. These animations are defined using two classes with distinct properties.

.line{
   height: 10px;
   width: 100px;
   margin: 10px;
   background-color:red;
}

@keyframes firstChild {
  0% {transform: translateY(0);}
  50% {transform: translateY(10px);}
  100% {transform: rotate(-45deg);}
}

@keyframes firstChild2 {
  0% {transform: rotate(-45deg);}
  50% {transform: translateY(10px);}
  100% {transform: rotate(0deg);}
}

.animate {
   animation-name: firstChild;
   transform-origin: 30px 25px;
   animation-duration: 0.5s;
   animation-fill-mode: forwards;
}

.reverse {
    animation-name: firstChild2;
   transform-origin: 30px 25px;
   animation-duration: 0.5s;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips on personalizing the DateTimePicker component from Material-UI

I am currently working on customizing the DateTimePicker component provided by Material-UI. To access its documentation, please visit: One challenge I have encountered is the lack of styling information in the documentation. My goal is to change the main ...

Switching a boolean value in Rails 4 using link_to

Looking to implement a link that can toggle a boolean value using ajax. I initially tried following this tutorial, but it wasn't compatible with rails 4. If anyone has advice on the best way to make this functionality work, I'd appreciate it. ...

Adjusting Anchor Links to Account for a Fixed Header

There have been a few posts discussing similar issues (like offsetting an html anchor to adjust for fixed header), but none of the solutions seem to work for my specific situation. I am currently using jQuery to generate a Table of Contents, following the ...

What is the reason behind LESS displaying arithmetic operations as text instead of performing them?

Whilst composing the subsequent operations @a: 2px @variable: @a + 5; .margin-style{ margin-left: @variable; } The code above compiles into .margin-style{ margin-left: 2px + 5; } Rather than margin-left:7px; What could be causing this issue? ...

Creating CSS wrappers around div elements of varying sizes

I am looking for a way to "wrap" different divs of varying sizes, similar to how Microsoft Word wraps text around an image. I have a simplified structure outlined below: <div id = "div1"></div> <div id = "div2"></div> <div id = ...

Using the novalidate attribute in Angular 4.0.0

Since migrating to angular 4, I have encountered a peculiar issue with my template-driven form. The required attribute on the input field appears to be malfunctioning. It seems like the form has the novalidate attribute by default, preventing HTML5 validat ...

What could be causing the issue of Vuejs 3.3 defineModel consistently returning undefined?

I am currently working with Nuxt version 3.5.1 and Vuejs version 3.3, however, I am encountering an issue where the defineModel macro always returns undefined. I am unsure why this is happening? <template> <input v-model="count"& ...

Guide on incorporating a JS file in a React application

I recently obtained a template for my website that includes the following JS file which is being called from my React component. !(function($) { "use strict"; // Hero typed if ($('.typed').length) { var typed_strings = $(&quo ...

Video player on website experiencing issues with playing VAST ads

Hey there! Check out this awesome site for Music Videos: (Music Videos(Player)) I've been testing different options, but if you have a better suggestion, please let me know. Any help would be really appreciated. If I can't figure it out on my o ...

retrieve data from jsp page using ajax request

I've coded this JSP snippet Map<String, Long> map = new HashMap<String, Long>(); map.put("A", 10L); map.put("B", 20L); map.put("C", 30L); JSONObject json = new JSONObject(); json.accumulate ...

The server mistakenly sent the resource as a Stylesheet even though it was interpreted differently

Dear Fellow Coders, Could anyone lend a hand? I encountered this issue on my website after uploading it to my FTP: "Resource interpreted as Stylesheet but transferred with MIME type text/plain" </head> <body> <div class= "navbar navbar ...

Tips on concealing the overflow content within a Material UI table cell, rather than allowing it to wrap around

I have been trying to use the material UI Table component in order to display a table. The issue I am facing is that when the content in a cell exceeds the allotted space, instead of showing ellipses (...), the text wraps within the cell. I attempted to ap ...

The art of styling <li> elements compared to <a> elements

While these inquiries may lean towards being subjective, I am interested in learning about the industry's generally accepted best practices: 1) With responsive design and collapsible menus becoming more common, should a nav or nav menu element be sty ...

Menu Items at the Center

I am currently working on a Wordpress website and struggling to center the menu items that are currently aligned to the left. I have created a child theme from the existing theme's code, but still can't figure out how to achieve this simple task. ...

Exploring Java Programming with HTMLEditorKit

Here is my source code: I am trying to change the font color using only CSS. This is how I am inserting HTML: <span class="tag1">I love <span class="tag2">apple</span></span><span class="tag2"> pie</span> When using ...

Static Sidebar integrated with Twitter Bootstrap version 2.3.5

Currently, I am in the process of learning how to incorporate a fixed sidebar using Twitter Bootstrap 2.3.5. Below is a snippet of the code I have been working on: <div class="container"> <div class="row"> <div class="span4" id="sid ...

Widget for navigating through Youtube videos

I am currently working on creating a widget that allows users to navigate a YouTube video using buttons. For instance, if the video is of a car race, there would be buttons labeled Lap 1, Lap 2, and so forth. My idea involves adding an extension to the vi ...

What is the preferred approach in JavaScript: having a single large file or multiple smaller files?

Having a multitude of JavaScript files loaded on a single page can result in decreased performance. My inquiry is this: Is it preferable to have individual files or combine them into one JavaScript file? If consolidating all scripts into one file is the ...

Tips for utilizing a select in a jQuery function

Recently, I've been working on some JavaScript code that involves appending options to select elements. Here is an example: var myuniqueddl = $('#myuniqueddl'); $("<option value='0'>--- Select a value ---</option>").a ...

Displaying JSON data after a successful AJAX call

I am currently facing an issue with my controller. I have a query that returns data in JSON format, and I'm trying to display this data in the view using AJAX and jQuery. However, every time I try to output the data, it shows as [object Object]. I sus ...