I'm currently trying to create a menu overlay that fills the screen when the user presses a button in the corner. I want the menu items to fade in, in a staggered order much like is done on the website here: http://bravepeople.co/

I have most of this working, however the menu items only fade in the first time the menu button is pressed, and then they just pop up the second time (with the exception of the first item). Can someone figure out how to get this working correctly?

Here's my code in CodePen.

Here's my html:

<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:

#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%;
}

#menu-button {
    position: absolute;
    left: 0;
    z-index: 2;
    width: 100px;
    height: 100px;
    background-color: #900;
    border: none;
    padding: 33px;
    right: calc(100% - 100px);
    -webkit-transition: left 0.5s, background-color 0.5s;
            transition: left 0.5s, background-color 0.5s;
    cursor: pointer;
}

#menu-button.active {
    left: calc(100% - 100px);
    right: 0;
    padding: 30px;
}

#menu-container {
    display: table;
    position: absolute;
    width: 100%;
    height: 100vh;
    text-align: center;
    z-index: 1;
    visibility: hidden;
}

#menu-container.active {
    visibility: visible;
}

#links {
    display: table-cell;
    vertical-align: middle;
    font-size: 40px;
    text-transform: uppercase;
}

#menu-container>#links>a {
    color: #fff;
    opacity: 0;
    -webkit-transition-timing-function: cubic-bezier(.81, .05, .75, .33);
            transition-timing-function: cubic-bezier(.81, .05, .75, .33);
}                                       

#menu-container.active>#links>a {
    opacity: 1;
}

#portfolio {
    -webkit-transition: opacity 0.5s;
            transition: opacity 0.5s;
}

#services {
    -webkit-transition: opacity 1s;
            transition: opacity 1s;
}

#about {
    -webkit-transition: opacity 1.5s;
            transition: opacity 1.5s;
}

#contact {
    -webkit-transition: opacity 2s;
            transition: opacity 2s;
}

and my Javascript:

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;

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);

edit: I forgot to mention that my original HTML uses a CSS file from Bootstrap which contains a reset. I've since added a link to a Bootstrap CDN.

2

There are 2 answers

0
Jinu Kurian On BEST ANSWER

The first answer makes sense and it well explained the problem in your code.

There is another way to solve the problem just by changing few codes in your CSS.

.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;
}

Add .active class before the menu-item. This makes the transition occur only when the menu-item has .active parent.

CODEPEN

0
WinterCore On

The problem you have is that after closing the menu the links need 2s to completely transition to opacity: 0; according to the one that has the longest transition time.

if you reopen it before 2s it will not work however you can solve this by setting the transition time to something small after closing the menu.

like this for example JsFiddle

you can edit your javascript to do this

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);

And include this in your css

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