Switching from a click event to a hover event in JavaScript

I've been experimenting with animating a burger bar on hover and came across an example online that I managed to adapt for mouseenter functionality. However, I'm struggling to make it revert back to the burger bar shape once the mouse leaves on mouseleave.

Below is the code snippet. While mouseenter is working as intended, I need help getting it to switch back to the burger bar icon when moving away from it instead of staying as an X.

(function() {"use strict";
  var toggles = document.querySelectorAll(".c-hamburger");
  for (var i = toggles.length - 1; i >= 0; i--) {
    var toggle = toggles[i];
    toggleHandler(toggle);
  };
  function toggleHandler(toggle) {
    toggle.addEventListener("mouseenter", function(e) {
      e.preventDefault();
      (this.classList.contains("is-active") === true) ? this.classList.remove("is-active"): this.classList.add("is-active");
    });
  }
             
})();
.c-hamburger {
  display: block;
  position: relative;
  overflow: hidden;
  margin: 0;
  padding: 0;
  width: 66px;
  height: 55px;
  font-size: 0;
  text-indent: -9999px;
  appearance: none;
  box-shadow: none;
  border-radius: none;
  border: none;
  cursor: pointer;
  transition: background 0.3s;
}

.c-hamburger:focus {
  outline: none;
}

.c-hamburger span {
  display: block;
  position: absolute;
  left: 18px;
  right: 18px;
  height: 2px;
  background: black;
}

.c-hamburger span::before,
.c-hamburger span::after {
  position: absolute;
  display: block;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: black;
  content: "";
}

.c-hamburger span::before {
  top: -10px;
}

.c-hamburger span::after {
  bottom: -10px;
}
.c-hamburger--htx {
  background-color: white;
}

.c-hamburger--htx span {
  transition: background 0s 0.3s;
}

.c-hamburger--htx span::before,
.c-hamburger--htx span::after {
  transition-duration: 0.3s, 0.3s;
  transition-delay: 0.3s, 0s;
}

.c-hamburger--htx span::before {
  transition-property: top, transform;
}

.c-hamburger--htx span::after {
  transition-property: bottom, transform;
}

/* active state, i.e. menu open */
.c-hamburger--htx.is-active {
  background-color: white;
}

.c-hamburger--htx.is-active span {
  background: none;
}

.c-hamburger--htx.is-active span::before {
  top: 0;
  transform: rotate(45deg);
}

.c-hamburger--htx.is-active span::after {
  bottom: 0;
  transform: rotate(-45deg);
}

.c-hamburger--htx.is-active span::before,
.c-hamburger--htx.is-active span::after {
  transition-delay: 0s, 0.3s;
}
<button class="c-hamburger c-hamburger--htx">
  <span>toggle menu</span>
</button>

Answer №1

To toggle a class on mouseenter and remove it on mouseleave events.

(function() {"use strict";
  var toggles = document.querySelectorAll(".c-hamburger");
  for (var i = toggles.length - 1; i >= 0; i--) {
    var toggle = toggles[i];
    toggleHandler(toggle);
  };
  function toggleHandler(toggle) {
    toggle.addEventListener("mouseenter", function(e) {
      e.preventDefault();
      this.classList.add('is-active');
    })
    toggle.addEventListener('mouseleave',function(e) {
      this.classList.remove('is-active');
    });
  }             
})();
.c-hamburger {
  display: block;
  position: relative;
  overflow: hidden;
  margin: 0;
  padding: 0;
  width: 66px;
  height: 55px;
  font-size: 0;
  text-indent: -9999px;
  appearance: none;
  box-shadow: none;
  border-radius: none;
  border: none;
  cursor: pointer;
  transition: background 0.3s;
}

.c-hamburger:focus {
  outline: none;
}

.c-hamburger span {
  display: block;
  position: absolute;
  left: 18px;
  right: 18px;
  height: 2px;
  background: black;
}

.c-hamburger span::before,
.c-hamburger span::after {
  position: absolute;
  display: block;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: black;
  content: "";
}

.c-hamburger span::before {
  top: -10px;
}

.c-hamburger span::after {
  bottom: -10px;
}
.c-hamburger--htx {
  background-color: white;
}

.c-hamburger--htx span {
  transition: background 0s 0.3s;
}

.c-hamburger--htx span::before,
.c-hamburger--htx span::after {
  transition-duration: 0.3s, 0.3s;
  transition-delay: 0.3s, 0s;
}

.c-hamburger--htx span::before {
  transition-property: top, transform;
}

.c-hamburger--htx span::after {
  transition-property: bottom, transform;
}

/* active state, i.e. menu open */
.c-hamburger--htx.is-active {
  background-color: white;
}

.c-hamburger--htx.is-active span {
  background: none;
}

.c-hamburger--htx.is-active span::before {
  top: 0;
  transform: rotate(45deg);
}

.c-hamburger--htx.is-active span::after {
  bottom: 0;
  transform: rotate(-45deg);
}

.c-hamburger--htx.is-active span::before,
.c-hamburger--htx.is-active span::after {
  transition-delay: 0s, 0.3s;
}
<button class="c-hamburger c-hamburger--htx">
  <span>toggle menu</span>
</button>

This behavior can also be achieved using CSS only.

.c-hamburger {
  display: block;
  position: relative;
  overflow: hidden;
  margin: 0;
  padding: 0;
  width: 66px;
  height: 55px;
  font-size: 0;
  text-indent: -9999px;
  appearance: none;
  box-shadow: none;
  border-radius: none;
  border: none;
  cursor: pointer;
  transition: background 0.3s;
}

.c-hamburger:focus {
  outline: none;
}

.c-hamburger span {
  display: block;
  position: absolute;
  left: 18px;
  right: 18px;
  height: 2px;
  background: black;
}

.c-hamburger span::before,
.c-hamburger span::after {
  position: absolute;
  display: block;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: black;
  content: "";
}

.c-hamburger span::before {
  top: -10px;
}

.c-hamburger span::after {
  bottom: -10px;
}
.c-hamburger--htx {
  background-color: white;
}

.c-hamburger--htx span {
  transition: background 0s 0.3s;
}

.c-hamburger--htx span::before,
.c-hamburger--htx span::after {
  transition-duration: 0.3s, 0.3s;
  transition-delay: 0.3s, 0s;
}

.c-hamburger--htx span::before {
  transition-property: top, transform;
}

.c-hamburger--htx span::after {
  transition-property: bottom, transform;
}

/* active state, i.e. menu open */
.c-hamburger--htx.is-active {
  background-color: white;
}

.c-hamburger--htx:hover span {
  background: none;
}

.c-hamburger--htx:hover span::before {
  top: 0;
  transform: rotate(45deg);
}

.c-hamburger--htx:hover span::after {
  bottom: 0;
  transform: rotate(-45deg);
}

.c-hamburger--htx:hover span::before,
.c-hamburger--htx:hover span::after {
  transition-delay: 0s, 0.3s;
}
<button class="c-hamburger c-hamburger--htx">
  <span>toggle menu</span>
</button>

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 return type of a server-side component in NextJS 14 when it is asynchronous

When using NextJS 14, I encountered a problem with the example provided in the documentation. The example is within the Page component, typically typed as NextPage. However, this type does not support the use of async await server components. In my case, ...

Dynamically including and deleting classes upon clicking using React

Looking for a solution to handle a list of links. The goal is to add a class called "is-active" when a link is clicked, while also removing any existing "is-active" classes from other links. Only one link should have the "is-active" class at a time. This ...

The dynamic data is not displaying on the Chart bundle JavaScript

I am currently utilizing chart bundle js for my project. While everything appears to be functioning properly on alter show, I am encountering an issue with the map display – nothing is showing up as intended. If anyone has a solution to resolve this iss ...

Jump to a specific section on a different page when the links are already equipped with anchors for smooth scrolling

My website has a menu on the home page that scrolls to specific id positions: <li><a href="#event-section">El evento</a></li> <li><a href="#asistentes-section">Asistentes</a></li> <li><a href="#cont ...

Manipulating divs by positioning them at the top, left, right, bottom, and center to occupy the entire visible portion of the page

Many suggest avoiding the use of table layouts and opting for divs and CSS instead, which I am happy to embrace. Please forgive me for asking a basic question. I am looking to create a layout where the center content stretches out to cover the entire visi ...

The setLanguage function in jsPDF does not support rendering different language characters

I'm currently working with jsPDF in Angular 2 and I'm experiencing an issue where my HTML content is not converting successfully into a PDF when it's written in Hebrew. Other languages seem to work fine, but Hebrew is causing a problem. How ...

Utilizing AngualarJS to bind data to intricate objects using the $resource functionality

Currently, I am working on a restful service that retrieves an order along with a list of items. In my project, I am developing a screen where users can edit specific items within the order. To achieve this, I need to display the list of items before locat ...

Separate a single large table into two smaller tables based on the information found in the third column of every row

Looking for a Greasemonkey script that can split a single table on a page into two separate tables based on a specific column. For example, if we have the following table: <table> <tr> <td>Jill</td> <td>Smith</td ...

Attempting to modify text using the header parameter has proven to be ineffective

pages/_middleware.ts import { NextRequest, NextResponse } from 'next/server'; const isMobile = (userAgent: string) => /iPhone|iPad|iPod|Android/i.test(userAgent); const propName = 'x-rewrite'; enum Device { desktop = 'no& ...

Closing the Material UI Drawer

Having an issue with my material UI drawer - I can open it successfully, but when attempting to close it, the event does not trigger. import React from 'react'; import './App.css'; import { fade, makeStyles } from '@material-ui/co ...

Uploading a photo via a jQuery AJAX request to a Model-View-Controller endpoint

I am facing an issue with the following code snippet: $("#preview").click(function () { $.ajax({ type: 'POST', url: '@Url.Action("Preview")', data: { color: $("#color-picker").val(), ...

Creating a front-end angular application with npm and grunt commands

Hello there! This marks my first question, so please bear with me if it's a bit unclear. I'm fairly new to application development and currently working on an AngularJS app using Grunt. My query revolves around the build process I've execut ...

Using a Promise to signal the completion of certain tasks

In our application, we have multiple controllers assigned to different tabs/pages. I am looking for a way to signal the completion of a task in one controller so that it can be used in another controller. I believe Promises are the solution for this, and I ...

Efficient ways to send both table rows and columns in a single parameter using ajax

I am seeking a way to efficiently send all selected row values from a table as a single parameter in an AJAX request. Below is the current code where I am sending them one by one using a forEach statement, which can impact performance when dealing with a l ...

iisnode ran into a problem while handling the request. Error code: 0x6d HTTP status code: 500 HTTP subStatus code: 1013

Currently, I am working on a web application using ReactJS for the frontend and Express for the backend. My deployment platform is Azure. In order to verify that my requests are being processed correctly, I decided to conduct two API tests. The first tes ...

Page rotates on hover effect with RotateY

How can I get an image to rotate on the Y axis when hovered over? My code works in -moz- but not in -webkit- or -o-. What am I missing? .spin-logo { height: 450px; margin: 0 auto; -moz-transition: transform 2000ms ease 0s; -o-animation: transfor ...

What is the reason for making the position of bg-container absolute?

Discover more about the "position: absolute" attribute Remove the position property for troubleshooting After testing this page in Chrome, I encountered a confusion regarding the usage of the position property within the bg-container. To my surprise, del ...

[quicksearch] Finding the amount of rows being displayed - simple tricks to know the count

I've successfully implemented TableSorter and QuickSearch plugins with jQuery. Now I'm looking to enhance my table by: Show row numbers dynamically for each displayed row Show the total number of displayed rows somewhere on the page ...

Received extra keys from getStaticPaths in NextJs

Currently engrossed in a project for a client using NextJs, The blog section comprises various paths like blog/[:category], blog/[:category]/[:post], and blog/author/[:author]. To achieve this, I am utilizing getStaticPaths and getStaticProps. My approach ...

Implementing a PHP form for seamless image uploads

I have been attempting to upload a form that includes an image. I have successfully retrieved the data for the brand name and other fields. However, I am encountering an issue with retrieving the image name and type. Can someone please assist me in ident ...