How come the cubic bezier timing function works flawlessly just on the first try when staggered transitioning element opacity over time with CSS and a touch of JS?

I'm currently working on a menu overlay that expands to fill the screen when a user clicks a button in the corner. I'd like the menu items to fade in one by one, similar to the effect used on this website:

Most of the functionality is there, but I'm facing an issue where the menu items only fade in smoothly the first time the button is clicked. After that, they just appear suddenly (except for the first item). Can anyone help me figure out how to fix this?

You can view my code on CodePen.

Here's the HTML snippet:

<html>
  <head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  </head>
  <body>
<div id="menu"></div>
<div id="menu-button"></div>
<div id="menu-container">
    <div id="links">
        <a href="#Portfolio" id="portfolio">Portfolio</a><br />
        <a href="#Services" id="services">Services</a><br />
        <a href="#About" id="about">About</a><br />
        <a href="#Contact" id="contact">Contact</a><br />
    </div>
</div>

My CSS styling:

#menu {
    position: absolute;
    top: 0;
    left: 0;
    width: 100px;
    height: 100px;
    z-index: 1;
    background-color: #111;
    -webkit-transition: width 0.5s, height 0.5s;
            transition: width 0.5s, height 0.5s;
}

#menu.active {
    width: 100%;
    height: 100%;
}
...

Javascript function:

let menu = {
    div: document.getElementById('menu'),
    button: document.getElementById('menu-button'),
    container: document.getElementById('menu-container'),
    isExpanded: false,
    adjust: function() {
        menu.isExpanded = !menu.isExpanded;
        if (menu.isExpanded) {
            menu.div.classList.add("active");
            menu.button.classList.add("active");
            menu.container.classList.add("active");
        } else {
            menu.div.classList.remove("active");
            menu.button.classList.remove("active");
            menu.container.classList.remove("active");
        }
    }
}
let links = document.getElementById('links').childNodes; 
...

Note: Initially, I omitted mentioning that my original HTML uses Bootstrap's reset CSS. I have since added a link to a Bootstrap CDN.

Answer №1

The explanation provided in the initial response effectively clarifies the issue with your code.

An alternative solution involves making slight adjustments to your CSS code.

.active #portfolio {
  -webkit-transition: opacity 1s;
  transition: opacity 1s;
}

.active #services {
  -webkit-transition: opacity 1.5s;
  transition: opacity 1.5s;
}

.active #about {
  -webkit-transition: opacity 2s;
  transition: opacity 2s;
}

.active #contact {
  -webkit-transition: opacity 2.5s;
  transition: opacity 2.5s;
}

To activate the transition only when the menu-item has the .active parent, simply add the .active class before the menu-item.

Check out the CODEPEN demo here!

Answer №2

Your issue stems from the fact that once you close the menu, the links take 2 seconds to fully transition to opacity: 0, based on the longest transition time set.

If you try to reopen the menu before 2 seconds have passed, it won't work properly. However, you can resolve this by reducing the transition time to a shorter duration after closing the menu.

Here is an example of how you can achieve this: JsFiddle

You can update your JavaScript code to implement this solution:

let menu = {
    div: document.getElementById('menu'),
    button: document.getElementById('menu-button'),
    container: document.getElementById('menu-container'),
    isExpanded: false,
    adjust: function() {
        menu.isExpanded = !menu.isExpanded;
        if (menu.isExpanded) {
            menu.div.classList.add("active");
            menu.button.classList.add("active");
            menu.container.classList.remove("finished");
            menu.container.classList.add("active");
        } else {
            menu.div.classList.remove("active");
            menu.button.classList.remove("active");
            menu.container.classList.add("finished");
            menu.container.classList.remove("active");
        }
    }
}

let links = document.getElementById('links').childNodes;

for (let i = 0; i < links.length; i += 1) {
    if (links[i].nodeName.toLowerCase() == 'a') {
        links[i].addEventListener('mouseup', menu.adjust);
    }
}  

menu.button.addEventListener('mousedown', menu.adjust);

Be sure to add the following CSS code as well:

#menu-container.finished>#links>a {
    -webkit-transition: opacity 0.1s;
            transition: opacity 0.1s;
}

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

How can you capture the VIRTUAL keyCode from a form input?

// Binding the keydown event to all input fields of type text within a form. $("form input[type=text]").keydown(function (e) { // Reference to keyCodes... var key = e.which || e.keyCode; // Only allowing numbers, backspace, and tab if((key >= 48 && ke ...

The CSS child selector seems to be malfunctioning as it is affecting all descendants of the specified type

Struggling with creating a menu containing nested lists. Attempted using a child selector (#menu-novo li:hover > ul) to display only immediate descendants, but all are still showing. Any suggestions or solutions for this issue? #menu-novo-container { ...

Arrangement of Bootstrap card components

Each card contains dynamic content fetched from the backend. <div *ngFor="let cardData of dataArray"> <div class="card-header"> <div [innerHtml]="cardData.headerContent"></div> </div> <d ...

All I desire is to eliminate the term "class" from the text

Upon clicking the code, only the value 137 should display according to the image. However, the word "class" also appears. https://i.stack.imgur.com/HZhr4.png <a rel="facebox" href="portal.php?id='.$rowa["_id"].' class="icon-remove"></a ...

Achieving opacity solely on the background within a div class can be accomplished by utilizing CSS properties such

Whenever I adjust the opacity of my main-body div class, it results in all elements within also becoming transparent. Ideally, I would like only the gray background to have opacity. See below for the code snippet: <div class="main1"> content </di ...

Image Carousel Extravaganza

Trying to set up a sequence of autoplaying images has been a bit of a challenge for me. I've attempted various methods but haven't quite nailed it yet. Take a look at what I'm aiming for: https://i.stack.imgur.com/JlqWk.gif This is the cod ...

"Hiding elements with display: none still occupies space on the

For some reason, my Pagination nav is set to display:none but causing an empty space where it shouldn't be. Even after trying overflow:hidden, visibility:none, height:0, the issue persists. I suspect it might have something to do with relative and ab ...

Moving object sideways in 100px intervals

I'm struggling to solve this issue. Currently, I have multiple div elements (each containing some content) that I need to drag and drop horizontally. However, I specifically want them to move in increments of 100px (meaning the left position should b ...

Unable to set the correct title view for mobile devices

We have successfully styled the products for desktop view and larger phones, but we are facing challenges in adjusting them properly for smaller phones. Below you will find a photo and corresponding code snippets: /* Products list - view list */ .product ...

What is the best way to position this dropdown menu component directly under a specific section of my navbar in a React application?

As I delved into creating a basic navbar and dropdown menu in React, I encountered a puzzling issue. I envisioned a section within the nav that would trigger a dropdown menu right below it upon hovering over it. Attempting to replicate this functionality b ...

Looking for assistance with aligning an image in a <td> cell that doubles as a link?

How can I center a play icon in the middle of a td cell and make the entire content clickable as a link, including the background image? I've tried various methods but can't seem to get it right without breaking the alignment. Any suggestions wou ...

Stop form from submitting on bootstrap input, still check for valid input

Encountering a dilemma here: Employing bootstrap form for user input and utilizing jQuery's preventDefault() to halt the form submission process (relying on AJAX instead). Yet, this approach hinders the input validation functionality provided by boots ...

Implemented an HTML hyperlink element precisely positioned

I have the following HTML code. I am trying to fix the position of an anchor tag called "View All" so that it stays in a specific location. However, whenever the value in the dropdown menu changes, the anchor tag moves according to the length of the new se ...

Change the button text without the need for a click, automatically switch

How can I make a button switch between 'click here' and 'download' every 2 seconds without requiring user interaction? The code I've tried so far is below, but it's not working as expected: <div class="assetClass customBut ...

Using a custom HTML file as a container in an Android WebView

I am trying to include each loaded page within my own custom HTML file. My app needs to first parse the loaded page, select the body tag, insert it into my custom HTML file, display it in a WebView, and continue this process for each subsequent page. I h ...

In AngularJS, the process of replacing text using a filter can be achieved by following

Currently in the process of learning Angular, but I've hit a roadblock and can't seem to find a solution. I have a website that provides USPS shipping options, and I need to replace the default text with my own. The vendor's option shows &ap ...

The E.js Template encountered an error with an unexpected token "else"

I am in the process of creating a website quickly using e.js & Express. However, I am encountering some problems when trying to use an if-else statement within e.js tags. The if statement works fine, but as soon as I add an else statement, things start t ...

Retrieving list item contents using PHP DOM scraping

Is it possible to use PHP DOM screen scraping to extract the content from an HTML tag named <li style="margin-top:10px"> that appears on one of my web pages? I am looking to retrieve all the data within the <li> tag and present it as HTML co ...

Launching Android Calendar app using Intent from a web browser (Chrome)

Did you know that you can use HTML links to open Android apps from within Chrome? Take a look at this resource. If you're trying to open the calendar app from an Android app, the intent should be content://com.android.calendar/time. Learn more about ...

Some CSS styles are not displaying correctly within an iframe

Let me start by clarifying that I am not looking to add extra CSS to the contents of an iframe from the parent document. My issue lies with a document that normally displays correctly but experiences styling issues when shown in an iframe. Whenever I searc ...