Switching back and forth between classes prevents the animation from playing continuously, causing it to jump straight to the end

Currently, I am in the process of animating a hamburger menu with a unique twist. The idea is to have the top and bottom lines smoothly translate to the middle and then elegantly rotate into an X shape when clicked. My approach involves toggling between two classes, namely menu-open and menu-closed using jQuery. However, I encountered a peculiar issue. When I removed the CSS for the menu-closed animation, everything worked perfectly. Yet, upon adding back the CSS, the animations seemed to skip directly to the final frame without fully executing.

CSS

.navbar .mobile-menu.menu-open .line::before {
        animation: menu-open-top 250ms linear forwards;
    }

    .navbar .mobile-menu.menu-open .line {
        animation: menu-middle 250ms linear forwards;
    }

    .navbar .mobile-menu.menu-open .line::after {
        animation: menu-open-bottom 250ms linear forwards;
    }

    .navbar .mobile-menu.menu-closed .line::before {
        animation: menu-open-top 250ms linear reverse;
    }

    .navbar .mobile-menu.menu-closed .line {
        animation: menu-middle 250ms linear reverse;
    }

    .navbar .mobile-menu.menu-closed .line::after {
        animation: menu-open-bottom 250ms linear reverse;
    }

Animation

@keyframes menu-open-top {
    30% {
        bottom: 0;
    }
    60% {
        bottom: 0;
        transform: rotate(0) translate(0);
    }
    100% {
        transform: rotate(45deg) translate(5px, 5px);
        visibility: visible;
    }
}

@keyframes menu-middle {
    40% {
        visibility: hidden;
    }
    to {
        visibility: hidden;
    }
}

@keyframes menu-open-bottom {
    30% {
        top: 0;
    }
    60% {
        top: 0;
        transform: rotate(0) translate(0);
    }
    100% {
        transform: rotate(-45deg) translate(6px, -6px);
        visibility: visible;
    }
}

JS

$(".mobile-menu").click(expandMenu);

function expandMenu() {
    $(".primary-nav").toggleClass("menu-expand");
    $(this).toggleClass("menu-open menu-closed");
}

I can't seem to figure out what's missing. It feels like there may be a need to introduce new keyframes for the reverse animation, but that could possibly be unnecessary.

Edit: To provide more context, here is the accompanying HTML code:

HTML

<div class="mobile-menu menu-closed">
  <div class="line"></div>
</div>

Answer №1

If you're looking to achieve a simple animation with precise timing, consider making changes to prop values. While @keyframe animations are an option, they can be trickier to control and synchronize, especially in cases like this where it's essentially a two-step animation.

To toggle the menu when clicking on a mobile menu button, you can use the following JavaScript code snippet:

document.querySelector('.mobile-menu').addEventListener('click', ({
  target
}) => {
  target.closest('.mobile-menu').classList.toggle('menu-open');
})

For those who prefer SCSS, here's a link to view the same functionality implemented in SCSS: https://jsfiddle.net/websiter/dybre2f9/. I've utilized CSS variables for easy customization and reusability. Feel free to adjust the values according to your preferences.

It's worth noting that the choice of using bottom and top properties for animating instead of translateY was intentional. This approach allows for independent movement animations, enabling experimentation with various overlapping values and timing functions. The slight overlap between rotation and movement adds a touch of organic fluidity to the animation, giving the impression that the button is dynamically responding to the interaction. It's all about infusing some liveliness into the design!

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

A form field leaves the container element, positioned to the far right using the `float: right;` CSS property

This is the content within the <body> tag. <div id="border"> <p><h1 style="text-align: center;">Welcome to XYZ Airline!</h1></p> <table caption="Select your preferred seat" style="margin-botto ...

Tips for correctly sending the response code from a Node.js API

I have a straightforward node-based API that is responsible for parsing JSON data, saving it into a Postgres database, and sending the correct response code (e.g., HTTP 201). Here is an excerpt of my code: router.route('/customer') .post(fu ...

Order of execution for setImmediate() and setTimeout() callbacks compared to I/O callbacks

In the world of Node.js, the event loop powered by libuv is divided into specific phases. The poll phase is where we wait for I/O tasks to complete before running their associated callbacks. The length of this waiting period is determined by timers, timeou ...

Achieving a draggable object to land on a designated target

Before you jump to conclusions based on the title, let me clarify that I am not referring to jQuery UI draggable. Instead, I am discussing a plugin that I am currently developing for the community. The goal of my plugin is to create a designated target fea ...

Utilizing Captcha with Meteor's accounts-ui-bootstrap-3 for enhanced security

Is it possible to incorporate Captcha verification when utilizing the combo of Meteor packages accounts-ui-bootstrap-3 and accounts-password? What is the process for integrating a package such as captchagen with accounts-ui? ...

The collapsible menu does not toggle when I tap on the icon

I am currently troubleshooting an issue with this link "https://sampledemos.online/training/index.html" where the toggle feature is not functioning properly. Below are the codes I have written: <aside id="layout-menu" class="layout-menu m ...

Having trouble importing JS into HTML file with NodeJS

I have created a web server using NodeJS that serves the file index.html. However, when I attempt to add a JavaScript file to my HTML document, the browser displays an error message stating The resource "http://localhost:3000/includes/main.js" was blocked ...

Styling with CSS and JavaScript: The ultimate method for desaturating multiple images

I am currently designing a portfolio website that will feature desaturated thumbnails of all my work. When you hover over each thumbnail, the color will fade in and out upon mouseover. Since this page will include numerous thumbnails, I have been contempl ...

Changing from system mode to dark mode or light mode

Within my Next.js web application, I am implementing MUI to facilitate the transition between system, light, and dark modes. Persistence between sessions is achieved by storing the selected theme in local storage. The user has the option to change the them ...

Creating animated effects that move an element to a specified distance away from

I have a jQuery function that allows me to scroll the page to a specific element when a button is clicked. $('#tour_btn_1').click(function(){ tourScrollTo('#tour_header_1'); }); function tourScrollTo(divData){ $('html, bo ...

Exploring the nuances between Ruby on Rails and the responses from json and JavaScript ajax

I am interested in learning the most effective method for handling an ajax request. Would it be better to send json data and parse it on the client side (for instance using pure), or should I generate javascript at the server side and send back the respo ...

The value control input does not get properly updated by ngModelChange

Having difficulty updating an input as the user types. Trying to collect a code from the user that follows this format: 354e-fab4 (2 groups of 4 alphanumeric characters separated by '-'). The user should not need to type the '-', as it ...

Is there a method to programmatically identify enterprise mode in IE11?

Is it possible to detect Internet Explorer 11 Enterprise mode programmatically? This would involve detecting at the server side using C# or JavaScript/jQuery. The discussion on the following thread has not reached a conclusive answer: IE 11 - Is there a ...

What is the best way to streamline JSON file data by selectively extracting necessary information?

After exporting my user data from Firebase, I am looking to streamline the JSON file by filtering only the necessary fields for my data model. The format of the file obtained from Firebase is as follows: { "Users": { "00uniqueuserid3& ...

Eliminating the need for RequireJS in the Typescript Visual Studio project template

After integrating RequireJS into my Typescript template using the nuget package manager, I found that it was more than what I needed and decided to uninstall it. Even though I removed the package through nuget and the files were deleted properly, my Typesc ...

Tips for displaying content when clicking on the opener containing tables or div elements

This is a snippet of JavaScript code $(document).ready(function () { $(".show-content").hide(); $(".opener").click(function () { $(this).parent().next(".show-content").slideToggle(); return false; ...

Angularjs directive retrieves infowindow DOM element from Google Maps

In order to apply some style fixes to the Infowindow, I am trying to select the element with the class 'gm-style-iw'. This selection process is taking place within an angularjs directive. <div ui-view="full-map" id="full-map" class="mainMap c ...

The class "pagination pagination-lg" from the link https://angular-ui.github.io/bootstrap/#/pagination seems to be malfunctioning in Bootstrap 4

Just starting out with angularjs and I'm trying to implement pagination using https://angular-ui.github.io/bootstrap/#/pagination. However, I'm facing an issue where the style class "pagination pagination-lg" is not applying properly. I'm cu ...

The function JSON.parse(data) may result in an undefined value being returned

data = { "users": [ [{ "value": "01", "text": "ABC XYZ" }], [{ "value": "02", "text": "XYZ ABC" }] ] } var jsonData = JSON.parse(data); for (var i = 0; i < jsonData.users.length; i++) { var userlist = json ...

Encountering an error when attempting to parse a JSON Object in Java from an AJAX call

** Latest Code Update ** My JavaScript and Ajax Implementation: $(function() { $("#create_obd").bind("click", function(event) { var soNumber = []; $('#sales_order_lineItems input[type=checkbox]:checked').eac ...