Issues with CSS transitions persisting despite switching from jQuery to Vanilla JS

Recently, I made the decision to switch the old code in my <head> from jQuery to Vanilla JS. Essentially, when you click on the hamburger icon, the mobile menu should fade-in and all the links should transition smoothly. I attempted to substitute the fadeToggle() function by adding the class mob-menu-show, along with a simple opacity transition, but it didn't work as expected. The same issue occurred with all the link translate transitions that were previously functioning with jQuery. With jQuery, everything ran seamlessly each time I opened the mobile menu. It seems like there might be an issue with the JavaScript code that is somehow preventing the transitions from executing properly, although the class mobile-menu-animations does activate since I can see the correct opacity change. Any assistance would be greatly appreciated, and I apologize for any messy code - I've just started delving into this.

HTML

<button class="hamburger hamburger--3dxy" type="button" aria-label="Menu" aria-controls="navigation">
  <span class="hamburger-box">
    <span class="hamburger-inner"></span>
  </span>
</button>

<div id="nav-fullscreen" class="mobile-menu mobile-menu-controls">
  <div id="mobile-menu-container">
    <div id="mobile-menu-content">
      <div id="logo-menu">
        <div id="logo-mobile-menu"><a href="https://#"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 69.5 8.57" class="logo">...</svg> </a></div>
      </div>
      <div id="nav-items">
        <div id="navigation">
          <ul>
            <li><a href="https://#">Item 1</a></li>
            <li><a href="https://#">Item 2</a></li>
            <li><a href="https://#">Item 3</a></li>
            <li><a href="https://#">Item 4</a></li>
          </ul>
        </div>
      </div>
      <div id="menu-mobile-button-cont"><a id="button-mobile-menu" href="#">Buy Now</a></div>
    </div>
  </div>
</div>

CSS

    .mobile-menu {
        display: none;
        opacity: 0;
        transition: opacity 0.2s;
    }
    
    .mob-menu-show {
      display: block !important;
      opacity: 1;
      transition: 0.2s opacity;
    }
    
    .mobile-menu-controls {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        background-color: #fff;
        z-index: 15;
    }
    
    #mobile-menu-container {
        flex-direction: column;
        display: flex;
        width: 100%;
        height: 100vh;
        align-items: stretch;
        top: 0;
        text-align: left;
        overflow-x: hidden;
        overflow-y: scroll;
    }
    
    #mobile-menu-content {
        width: 100%;
        flex-direction: column;
        display: flex;
        align-items: stretch;
        max-width: 1280px;
    }
    
    #nav-items {
        flex-direction: unset;
        margin-top: 7rem;
    }
    
    #menu-mobile-button-cont {
        margin-left: 20px;
        margin-bottom: 26px;
        margin-right: 20px;
        text-align: left;
        flex-direction: unset;
        display: flex;
        width: 100%;
        margin-top: 8rem;
    }

/* Transitions */
    
    #button-mobile-menu {
        opacity: 0;
        margin-left: 40px;
        transform: translateX(0px);
        transition: transform .2s,opacity .2s;
    }
    
    #logo-mobile-menu {
      opacity: 0;
      padding-left: 40px;
      transform: translateX(0px);
      transition: transform 0.2s, opacity 0.2s;
    }
    
    .mobile-menu-controls li {
      opacity: 0;
      padding-left: 40px;
      transform: translateX(0px);
      transition: transform 0.2s, opacity 0.2s;
    }
    
    #button-mobile-menu {
      opacity: 0;
      margin-left: 40px;
      transform: translateX(0px);
      transition: transform 0.2s, opacity 0.2s;
    }
    
    .mobile-menu-animations #logo-mobile-menu {
        transform: translateX(-40px);
        transition: transform 0.2s, opacity 0.2s;
        transition-timing-function: ease, ease;
        opacity: 1;
        transition-delay: 0.1s;
    }
    
    .mobile-menu-animations li {
        transform: translateX(-40px);
        transition: transform 0.2s, opacity 0.2s;
        transition-timing-function: ease, ease;
        opacity: 1;
    }
    
    .mobile-menu-animations li:nth-child(1) {
        transition-delay: 0.2s;
    }
    
    .mobile-menu-animations li:nth-child(2) {
        transition-delay: 0.3s;
    }
    
    .mobile-menu-animations li:nth-child(3) {
        transition-delay: 0.4s;
    }
    
    .mobile-menu-animations li:nth-child(4) {
        transition-delay: 0.5s;
    }
    
    .mobile-menu-animations #button-mobile-menu {
        transform: translateX(-40px);
        transition: transform 0.2s, opacity 0.2s;
        transition-timing-function: ease, ease;
        opacity: 1;
        transition-delay: 0.6s;
    }
    
/* Prevent body scroll */

    .prevent-scroll {
      overflow: hidden;
    }

Old jQuery Code

$(document).ready(function() {
  $('.hamburger').click(function() {
    $('.hamburger').toggleClass('is-active');
    $('.mobile-menu').fadeToggle(350);
    $('.mobile-menu-controls').toggleClass('mobile-menu-animations');
    $('body').toggleClass("prevent-scroll");
  });
});

Converted JS

document.addEventListener("DOMContentLoaded", function(event) { 

  let hamb = document.querySelector('.hamburger')
  let mobmenu = document.querySelector('.mobile-menu')
  let mobanim = document.querySelector('.mobile-menu-controls')
  let bdy = document.querySelector('body')

  hamb.addEventListener('click', function(e) {
      this.classList.toggle('is-active');
      mobmenu.classList.toggle('mob-menu-show');
      mobanim.classList.toggle('mobile-menu-animations');
      bdy.classList.toggle('prevent-scroll');
  });
});

Answer №1

As pointed out by others, using the display css attribute for transitions can be troublesome. A better approach is to utilize keyframes and animations. In this example, I am only animating the opacity, but you should update other transitions to use keyframes as well.

let hamb = document.querySelector('.hamburger')
let mobmenu = document.querySelector('.mobile-menu')
let mobanim = document.querySelector('.mobile-menu-controls')
let bdy = document.querySelector('body')

hamb.addEventListener('click', function() {
  hamb.classList.toggle('is-active');
  bdy.classList.toggle('prevent-scroll');
  mobmenu.classList.toggle('mob-menu-show');
  mobanim.classList.toggle('mobile-menu-animations');
});
@keyframes fade {
  0% {
    opacity: 0;
  }
}

.mobile-menu {
  display: none;
}

.mob-menu-show {
  opacity: 1;
  display: block;
  animation: fade .250s both;
}

/* Rest of CSS code omitted for brevity */
<button class="hamburger hamburger--3dxy" type="button" aria-label="Menu" aria-controls="navigation">
  <span class="hamburger-box">
    <span class="hamburger-inner"></span>
  </span>
</button>

<div id="nav-fullscreen" class="mobile-menu mobile-menu-controls">
  <div id="mobile-menu-container">
    <div id="mobile-menu-content">
      <div id="logo-menu">
        <div id="logo-mobile-menu">
          <a href="https://#"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 69.5 8.57" class="logo">...</svg> </a>
        </div>
      </div>
      <div id="nav-items">
        <div id="navigation">
          <ul>
            <li><a href="https://#">Item 1</a></li>
            <li><a href="https://#">Item 2</a></li>
            <li><a href="https://#">Item 3</a></li>
            <li><a href="https://#">Item 4</a></li>
          </ul>
        </div>
      </div>
      <div id="menu-mobile-button-cont"><a id="button-mobile-menu" href="#">Buy Now</a></div>
    </div>
  </div>
</div>

Alternatively, if you prefer not to keyframe all your transitions, you can achieve similar results using JavaScript like this:

  1. Manually set the display attribute to block on click.
  2. Use setTimeout to wait for styles to be flushed to the DOM.
  3. Add the necessary classnames.

let hamb = document.querySelector('.hamburger')
let mobmenu = document.querySelector('.mobile-menu')
let mobanim = document.querySelector('.mobile-menu-controls')
let bdy = document.querySelector('body')

hamb.addEventListener('click', function() {
  hamb.classList.toggle('is-active');
  bdy.classList.toggle('prevent-scroll');
  mobmenu.style.display = "block";

  setTimeout(() => {
    mobmenu.classList.toggle('mob-menu-show');
    mobanim.classList.toggle('mobile-menu-animations');
  });
});
.mobile-menu {
  display: none;
  opacity: 0;
  transition: opacity .250ms;
}

.mob-menu-show {
  opacity: 1;
}

/* Rest of CSS code omitted for brevity */
<button class="hamburger hamburger--3dxy" type="button" aria-label="Menu" aria-controls="navigation">
  <span class="hamburger-box">
    <span class="hamburger-inner"></span>
  </span>
</button>

<div id="nav-fullscreen" class="mobile-menu mobile-menu-controls">
  <div id="mobile-menu-container">
    <div id="mobile-menu-content">
      <div id="logo-menu">
        <div id="logo-mobile-menu">
          <a href="https://#"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 69.5 8.57" class="logo">...</svg> </a>
        </div>
      </div>
      <div id="nav-items">
        <div id="navigation">
          <ul>
            <li><a href="https://#">Item 1</a></li>
            <li><a href="https://#">Item 2</a></li>
            <li><a href="https://#">Item 3</a></li>
            <li><a href="https://#">Item 4</a></li>
          </ul>
        </div>
      </div>
      <div id="menu-mobile-button-cont"><a id="button-mobile-menu" href="#">Buy Now</a></div>
    </div>
  </div>
</div>

Answer №2

To hide an element on a webpage, consider using visibility: hidden;

Avoid using display: none if you want to include transitions.

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

Signing out of Firebase Authentication - using Node.js

Currently, I am utilizing Firebase for user management. The method firebase.auth().signInWithEmailAndPassword() is used for user sign-in and it operates smoothly. However, when attempting to sign out with the firebase.auth().signOut() method, it triggers a ...

Find the elements of <a> tags specifically without the attribute href

Currently, I am extracting the class of all <a> elements in an HTML document of a webpage using VB.net from a WinForm: Dim htmlLinks As HtmlElementCollection = WebBrowser1.Document.GetElementsByTagName("a") For Each link As HtmlElement In htmlLi ...

Utilize Bootstrap to expand a row with 24 responsive columns and fill the remaining vertical space

Hello everyone! This is my first time posting a question here, even though I've been relying on this site for solutions for several years now. I've encountered a "multi-row" issue that seems to be unique and hasn't been covered yet. Despite ...

Using MySQL data in an EJS file to create a personalized Profile Page

In the midst of a personal project aimed at honing my web development skills and gaining a deeper understanding of the intricacies of the field, I have hit a roadblock. The focus of this project is to create a profile page, and while I have successfully co ...

Using the && operator in an if statement along with checking the length property

Why does the console show 'Cannot read property 'length' of undefined' error message when I merge two if conditions together? //When combining two if statements using &&: for(n= 0, len=i.length; n<len; n++) { if(typeof ...

Preventing a hyperlink from following its destination path

Hey there, I'm having trouble preventing a link from carrying out its default action. Here's the code I'm using: $("a.delete").on("click", function (e) { var container = $("#lightbox-background"); var lightbox = $("#lightbox"); ...

What is the best approach to storing and retrieving special characters ('+<>$") from a textfield into a database using PHP?

I have a form where users can enter a personal message with a subject. The data entered in the textarea is passed to a Javascript/jQuery function, which then sends it to a PHP file for storage in a database. However, I am encountering issues when special c ...

The problem arises when Angular's $interval function is not recognized

Despite the possibility of this being considered a duplicate, none of the related topics have provided a solution to my simple date count down directive: class Clock { constructor() { this.restrict = 'AC'; this.replace = true ...

Search with grep function that ignores letter case in indexOf

I am currently working on a project using IndexOf and $.grep in jQuery to search through a list of values. I require a case insensitive search, however, I am running into issues with case sensitivity. I have browsed similar solutions on StackOverflow, but ...

I have a query regarding the process of filtering data, specifically in the context of

When working with express and mongoose, I often encounter complex queries. As a workaround, I typically retrieve objects by their ID like this: const ticketObj = await Ticket.findById(ticketId); I then use JavaScript's filter method to further narro ...

Trouble arising from Bootstrap 5's float-end on flex items

When I apply the float-end class, it shifts the button to the right, but the div tags next to it appear in front of it. https://i.sstatic.net/Mxu0P.png <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protecti ...

Struggling to keep the footer anchored at the bottom of the page

When the content on an HTML page is minimal, the footer may end up positioned halfway up the page, creating a blank space below. This can be unappealing, especially on larger screens. Designers are frequently tasked with moving footers to the bottom of the ...

Adjustable size for web page elements

I am currently designing a web page using a basic template structure. The layout includes a header, top navigation bar, side navigation panel, main content area, and footer. While working on this project, I created a similar design in a jsfiddle demo. Ho ...

Ways to organize interconnected form elements on a PHP webpage

On my PHP page, I have a form designed to gather user information for job recruitment. This form consists of multiple input fields and can be considered as a candidate's resume. One section of the form requires users to enter their skill set in the f ...

Having difficulty applying parseFloat directly following a JSON Stringify operation

There's a specific line of code I'm working with that reads -- let longitude = JSON.stringify(place.lon); After calling alert(longitude), I receive the output "44.54321". However, my intention is to retrieve just the number itself, so I attempt ...

Shut down the elegant box using the function housed within the 'fancybox' opening

Hey everyone! I'm looking for a way to close fancyBox when it's already open. I've attempted the code below without any success: function closeFancyBox(html){ var re = /.*Element insert complete!.*/gi; if( html.search( re ) == 0 ){ ...

Coming back from retrieving data from an API

I'm having trouble with a function that performs a POST request to retrieve access tokens from an API. Although the function successfully prints the token to the console, I haven't been able to figure out how to properly parse and save the access ...

Several radial progress charts in JavaScript

While attempting to recreate and update this chart, I successfully created a separate chart but encountered difficulties with achieving the second progress. The secondary chart <div id="radial-progress-vha"> <div class="circle-vha ...

Issue with Selenium: Unable to select the WebElement

I am a beginner with selenium and I have encountered a problem while trying to click on a specific element using the following locators. Unfortunately, none of them seem to work as expected and my scripts just skip over that particular line without any err ...

What are some methods for transferring the state variable's value from one component to another in React?

I have the following scenario in my code: there is a Form.js component that interacts with an API, stores the response in the walletAssets state variable, and now I want to create a separate Display.js component to present this data. How can I pass the v ...