Animate CSS with Javascript in reverse direction

Forgive me if this is a silly question, but I'm having trouble. I need a slide-in navigation menu for smaller screens that is triggered by JavaScript. Here is what I currently have:

HTML

<nav class="responsive">
  <ul class="nav-list unstyled">
    <li class="nav-item"><a href="#">Shop</a></li>
    <li class="nav-item"><a href="#">Our Story</a></li>
    <li class="nav-item"><a href="#">Information</a></li>
    <li class="nav-item"><a href="#">Magazine</a></li>
    <li class="nav-item"><a href="#">Contact</a></li>
  </ul>
</nav>

SCSS

nav.responsive {
  ul {
    text-align: center;
    list-style-type: none;
    padding: 0;
    margin: 0;
    display: none;
    transform: translateX(-100%);
    background-color: #fafafa;
    li {
      a {
        display: block;
        padding: 12px;
        border-bottom: 1px solid #dadada;
      }
    }
    &.menu-list-active {
      display: block;
      animation: slide-in 0.5s forwards;
    }
  }

  @media only screen and (min-width: 720px) {
    ul {
      display: block;
      transform: none;
      li {
        display: inline-block;
        a {
          border-bottom: none;
        }
      }
    }
  }

  div.nav-mobile {
    display: block;
    height: 48px;
    width: 48px;
    position: absolute;
    top: 0;
    right: 0;
    background-color: #999999;
    cursor: pointer;
    &.menu-button-active {
      background-color: #555555;
    }
    @media only screen and (min-width: 720px) {
      display: none;
    }
  }
}

@keyframes slide-in {
    100% { transform: translateX(0); }
}

Javascript

// Create the mobile navigation toggle button

var mobile = document.createElement('div');
mobile.className = 'nav-mobile';
document.querySelector('nav.responsive').appendChild(mobile);

// Set some variables

var mobileNav = document.querySelector('.nav-mobile');
var navList = document.querySelector('.nav-list');

// Handle showing the menu
mobileNav.onclick = function () {
  this.classList.toggle('menu-button-active');
  navList.classList.toggle('menu-list-active');
};

The current setup is functioning as intended, with the menu sliding in nicely. However, I also want it to slide out when the nav-mobile button is clicked. I attempted animating the ul initially, but that caused the menu to slide out when the screen size was reduced, which is not desired. Ideally, the menu should be hidden when the page loads on a small screen.

Is there a way to achieve this functionality?

EDIT

Check out the Codepen here:

Answer №1

Consider implementing a transition rather than an animation in this scenario. Here is an example for better understanding:

document.querySelector('div').addEventListener('click', function(){
  this.classList.toggle('active');
})
div {
  width: 100px;
  height: 200px;
  background: red;
  position: absolute;
  left: 0;
  top: 0;
  transform: translateX(-100%);
  transition: transform .4s;
}

div:after {
  content: '';
  width: 20px;
  height: 20px;
  display: block;
  position: absolute;
  left: 100%;
  top: 0;
  background: blue;
}

div.active {
  transform: translate(0);
}
<div>My Nav</div>

This alternative approach achieves similar animation results like the one you are currently using, but with the added benefit of being interruptible. Additionally, by utilizing :before or :after and detecting clicks directly on the wrapper in JavaScript, you can simplify your HTML structure and design your menu entirely in CSS to reduce clutter.

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

The parameter label is being detected as having an any type, as specified in the Binding element 'label'

Currently, I am referencing an example code snippet from react-hook-form. However, upon implementation, I encounter the following error: (parameter) label: any Binding element 'label' implicitly has an 'any' type.ts(7031) The example c ...

I am having trouble starting a server on localhost with the command npm run dev

Currently, I am in the process of developing a website using react.js and tailwindcss. However, when attempting to test my progress by running the "npm run dev" command, I discovered that it is not starting a server on localhost. I am unfamiliar with this ...

Trouble with Contact Form: PHP failing to display INPUTs

I've been grappling with this issue for a few days now, scouring through countless questions and tutorials. The Contact Form on my website seems to be working—it submits, confirms, and redirects as expected. However, there's one major problem: ...

Individuals have the capability to utilize .php as an image extension

It seems that someone is able to use any type of extension as long as they add .png at the end of the link. is currently being used, causing users on my website to log out when visiting the homepage. I tried to stop this issue, but unfortunately, my sol ...

How can we optimize ternary statements within ternary statements in Type Script and React Native for best practices?

Can you help me optimize this code snippet that uses nested ternary operators for better readability and correctness? <TouchableOpacity style={ darkMode ? filterState === 'A' ? styles.activeButtonDark : styles.buttonDa ...

CKEditor with Readonly Option and Active Toolbar Controls

In my current Rails project, I have successfully set up a CKEditor instance in readOnly mode. Everything is functioning as expected. Now, I am attempting to add a custom plugin button to the toolbar while keeping the textarea in readOnly mode. After some ...

Tips for transferring input field values through the href attribute in HTML?

How can I pass an integer value from a link to an input field's value? Imagine example.com is a webpage with one input field. I would like to achieve something like this: Click here 1 Click here 2 If the user clicks on click here 1, then ...

Tips for eliminating unnecessary space in a text area

I have a textarea and a button. I wanted them to be placed in the same horizontal line from the bottom. However, when I place them inline with no style applied, there is extra margin at the bottom of the textarea that is causing them not to align properly: ...

Encountering a 405 error when attempting to send a request through an express route in a Next

After deploying my Express js routes in Next js on hosting, I encountered an error 405 when sending requests to the route. However, everything works fine when I test it on localhost. I'm puzzled by this issue. Can anyone help me understand what' ...

"Is it possible to access variables declared in the main app.js file from separate route files in Node.js Express 2.5.5 and if so

Recently, I've started using the latest version of Express (2.5.5) which now automatically creates a ./routes directory in addition to ./views and ./public In the routes directory, there is an index.js file that includes: /* * GET home page. */ e ...

Failure occurred when attempting to redirect in HTML

Within my HTML code snippet, I have included a section that pertains to notifications. The main issue I am encountering is related to the redirection behavior when clicking on the "Home" link inside the designated notification container with the ID "notifi ...

The definition of Csrftoken is missing

The code I am currently using, as per the recommended documentation, is: function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); ...

Sliding with JavaScript

I'm looking to develop a unique web interface where users can divide a "timeline" into multiple segments. Start|-----------------------------|End ^flag one ^flag two Users should be able to add customizable flags and adjust their position ...

Extract the URL parameter and eliminate all characters following the final forward slash

Here is the URL of my website: example http://mypage.com/en/?site=main. Following this is a combination of JavaScript and PHP code that parses the data on the site. I am now looking for a piece of code that can dynamically change the URL displayed in the ...

CSS border alignment techniques

I am attempting to achieve the effect of having an orange border on top of a blue border, with only the orange border moving. I have noticed this design feature on various websites but have been unable to replicate it without removing the padding of the pa ...

Is there a way to determine when the callback function has been called for the final time?

Per the documentation on String.prototype.replace(), if a function is passed to String.replace() with a global regular expression, it will be invoked multiple times. Is there a way to pass a callback within this callback to determine when all invocations ...

Guide on creating multiple instances of vue-multiselect with a simple button click

I am trying to implement a vue-multiselect dropdown with the addition of a new dropdown upon clicking an "add more" button. However, I am currently unsure of the best approach to achieve this. Problem/Question: When adding 2 dropdowns, if the same option ...

Is it possible to recognize when the mouse button is held down and the cursor is outside the viewport by using mouseleave detection?

Is there a way to detect when a user moves the mouse outside of the view-port, even if they are holding down the mouse button (for example, if the mouse is on the browser address bar)? In the code below, I am currently using mouseout and mouseleave to det ...

The radio button in the HTML form is disabled when the user selects

I have two radio buttons labeled Billable "Y" and Billable "N". These radio buttons are linked to a database with corresponding values of "Y" or "N". If the user selects "Y" using the radio button, then the NonBillableReason text box should be disabled. ...

Issue with MomentJS inBetween function consistently displaying incorrect results

I'm currently working on Vue Datatable and I have a specific requirement to search for records between two dates. I am using the moment.js library and the inBetween function to achieve this. Strangely, when I hardcode the dates, the function returns t ...