Using pure JavaScript, implement a transition effect that changes an element's display from

My goal is to create an animation where a hidden menu box slides down and appears when the mouse hovers over a button. The animation works correctly, but I encountered an issue when trying to add the transition from display:inline-block to display:none and back to display:inline-block, as the transition disappears.

I've come across solutions in jQuery, but none in pure JavaScript, except for one using EventListener which I found challenging to implement in my case.

I attempted to split the JS into two functions—one for displaying the block and another for changing the class—but it didn't work. One solution might be to include an EventListener that triggers a function after the display property is modified (simply adding it in JS doesn't seem to suffice). Any assistance on this matter would be greatly appreciated.

Here's the code snippet:

function overbutton(divname) {
  element = document.getElementById(divname);
  if (element.className == "menu_hidden menu_about") {
    //element.style.display ="inline-block";
    element.className = "menu_shown menu_about";
  } else {
    //element.style.display ="none";
    element.className = "menu_hidden menu_about";
  }
}

function onmenu(divname) {
  //element.style.display ="inline-block";
  element = document.getElementById(divname);
  element.className = "menu_shown menu_about";
}

function outmenu(divname) {
  //element.style.display ="none";
  element = document.getElementById(divname);
  element.className = "menu_hidden menu_about";
}
.menu_about {
  background-color: white;
  height: 100px;
  width: 100px;
  top: 20px;
  left: 50px;
  border-radius: 10px;
  box-shadow: 0px 0px 10px #2B2B2B40;
  -webkit-box-shadow: 0px 0px 10px #2B2B2B40;
  -moz-box-shadow: 0px 0px 10px #2B2B2B40;
  position: absolute;
  padding: 20px;
}

.menu_hidden {
  -webkit-transform: translate(0%, -5px);
  transform: translate(0%, -5px);
  transition: transform 0.3s;
  -webkit-transition: -webkit-transform 0.3s;
}

.menu_shown {
  -webkit-transform: translate(0%, 5px);
  transform: translate(0%, 10px);
  transition: transform 0.3s;
  -webkit-transition: -webkit-transform 0.3s;
}
<div style="padding-left:100px">

  <button class="button-menu" onmouseover="overbutton('about_menu_div')" onmouseout="overbutton('about_menu_div')">
    menu Button
  </button>

  <!-- add style="display:none;"-->
  <div id="about_menu_div" class="menu_hidden menu_about" onmouseover="onmenu('about_menu_div')" onmouseout="outmenu('about_menu_div')">
    Menu
  </div>

</div>

JSfiddle: https://jsfiddle.net/g0ktx574/

Answer №1

If you want to achieve this effect without using JavaScript, you can do so with CSS. By utilizing the :hover pseudo-class and the + adjacent sibling selector, you can create the desired behavior.

It's important to note that the display property cannot be animated. Instead, consider using opacity in conjunction with visibility for a smoother transition effect.

.wrapper {
  position: relative;
}

.menu_about {
  position: absolute;
  top: 100%;
  left: 0;
  background-color: white;
  height: 100px;
  width: 100px;
  padding: 20px;
  border-radius: 10px;
  box-shadow: 0px 0px 10px #2B2B2B40;
  opacity: 0;
  visibility: hidden;
  transition-property: opacity visibility transform;
  transition: 0.3s;
}

.button-menu:hover + .menu_about,
.menu_about:hover {
  opacity: 1;
  visibility: visible;
  transform: translate(0%, 5px);
}
<div class="wrapper">
  <button class="button-menu">
    menu Button
  </button>

  <div class="menu_about">
    Menu
  </div>
</div>

Answer №2

After coming across the solution provided in this Stack Overflow thread, I decided to tweak the code based on it. It's important to note that you can't animate the display property directly. Therefore, my adjusted solution utilizes the setTimeout function to achieve the desired animation effect by manipulating the transform property. I made some CSS adjustments as well for a cleaner look. Feel free to check it out and customize the transition timing and transform properties to suit your requirements.

function overButton(divName) {
    const element = document.getElementById(divName);
    if (element.className === "menu_hidden menu_about") {
        element.style.display ="inline-block";
        element.className = "menu_shown menu_about";
        element.style.transform  = "translate(0%, 10px)";
        element.style.transition = "transform .7s";
        setTimeout(function() {
            element.style.transform = 'translate(0%, 30px)';
            element.style.transition = "transform .7s";
        }, 0)
    } else {
        element.style.display ="none";
        element.className = "menu_hidden menu_about";
    }
}

function onMenu(divName) {
    const element = document.getElementById(divName);
    element.style.display ="inline-block";
    element.className = "menu_shown menu_about";    
}

function outMenu(divName) {
    const element = document.getElementById(divName);
    element.style.display ="none";
    element.className = "menu_hidden menu_about";
}
.menu_about{
    background-color:white; 
    height:100px;             
    width:100px; 
    top:20px; 
    left:50px;
    border-radius: 10px;
    box-shadow: 0px 0px 10px #2B2B2B40;
    -webkit-box-shadow: 0px 0px 10px #2B2B2B40;
    -moz-box-shadow: 0px 0px 10px #2B2B2B40;
    position: absolute;
    padding: 20px;
}

/* Hide Menu Initially */
.menu_hidden {
    display: none;
}
<div style="padding-left:100px">

        <button class="button-menu" onmouseover="overButton('about_menu_div')" onmouseout="overButton('about_menu_div')">
          Menu Button
        </button>
      
      <!-- Add style="display:none;"-->
        <div id="about_menu_div" class="menu_hidden menu_about" onmouseover="onMenu('about_menu_div')" onmouseout="outMenu('about_menu_div')">
          Menu
    </div>
</div>

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 come AJAX is not successfully processing the image file?

It's puzzling that the image file in the form is being processed without any issues when Ajax is not used, but encounters a problem with the Ajax script provided below. I'm struggling to understand why this discrepancy exists... Please note: Th ...

What is the method for placing a badge above a Font Awesome icon?

Is it possible to add a badge with numbers like 5, 10, or 100 on top of the Font Awesome symbol (fa-envelope)? I am looking for something like this: However, I am struggling to figure out how to place the badge on top of the symbol. You can see my attempt ...

Can you explain the rationale behind html and js?

I am experiencing an issue with my code. When I click on the "click" button, the color changes as expected but the console log is showing that the code is not working according to the logic I have implemented. Initially, the color is black which is correc ...

Managing post requests within the express.js framework

I need assistance utilizing the value provided in a form within Node.js. Here is an example: index.html : <!DOCTYPE html> <html lang="en"> <head> </head> <body> <div align="middle" > <!--Ethernet ...

Am I on the right track with incorporating responsiveness in my React development practices?

Seeking advice on creating a responsive page with React components. I am currently using window.matchMedia to match media queries and re-rendering every time the window size is set or changes. function reportWindowSize() { let isPhone = window.matchMed ...

find the text that is not encompassed by a particular html tag

After coming across this inquiry, I am curious about how one can detect text that is not within a particular HTML tag. desired text: "targetstring" excluding the script HTML tag <div> <h1>targetstring</h1> <= should be detected ...

Increase the size of an image when the mouse hovers over it within a

Recently, I came across this tutorial on creating a zoom in effect for images when hovering over them with the mouse. The tutorial doesn't use tables to display the images, so I was wondering if I could achieve the same effect by placing the images in ...

Delete the hidden attribute from an HTML element using a JavaScript function

Hey there! I have a question for you. Can you assist me in removing an attribute (Hidden) using an Input type button? Here is the script: Thank you for your help! <input type="button" onclick="myfunction()" value="Test"> <hr> <button id= ...

What is an effective method for coordinating JQuery animations simultaneously?

My current understanding of $("#someElement").animate() is that it will run asynchronously in relation to other JavaScript statements. For example: $("#anotherElement").css("display", "none"); $("#someElement").animate(); //The CSS display may change a ...

Implementing conditional styling in Vue.js using v-bind based on specific Bootstrap breakpoints

Is there a way to dynamically assign styles based on different bootstrap breakpoints using v-bind style directive with vue? I'm encountering an error in the console that says "Whitespace was expected." <div class="footer" :style="{$b ...

encountering problems with Next.js routing resulting in 404 errors

I developed a Next Js 14 app where I had to change the routing names inside the pages before going live. For example, instead of 'Charts', I changed it to 'charts' and made similar modifications to other pages as well. However, after de ...

Issue with min-height property in IE8 (and potentially other browser versions)

Trying to design a web page with 3 sections, each occupying 100% of the window height. Managed to make it work on Chrome, Firefox, and Safari, but facing compatibility issues with IE8 and possibly other versions. Test out the page here: Here's the H ...

Is feature recognition possible in a jQuery plugin?

Can I integrate a tool similar to Modernizr into my plugin? I want to be able to test for specific CSS3 properties without starting from scratch. ...

Guide to exporting specific files in Node.js or Deno

Utilizing the export keyword in JavaScript allows us to export any content from one file to another. Is there a way to restrict exports to specific files, preventing other files from importing them? export const t = { a: 'this will only be exported fo ...

Having trouble combining different styles with Material-ui and Radium?

Trying to integrate Radium with Material-ui has presented a challenge. Attempting to apply multiple styles to a single Material-ui component results in no styling being applied. For instance, the following code fails to render any styling: <MenuItem st ...

Debounce on React Component

Attempting to add a delay to a react component with an input field that updates when changed Below is the method used for onChange: handleOrderQtyKeyPress (e) { var regex = /[^0-9]/ if (e.key.match(regex)) { e.preventDefault(); } ...

Restarting a JavaScript function upon switching views in Vue.js

I am new to working with Vue.js and I have a Laravel app that utilizes it. One issue I am facing is that when the homepage is loading, all elements like owl carousel and rev slider are initialized. However, if I navigate to other routes such as contact or ...

What is the method to modify the background color of el-pagination?

I am using el-pagination on a dark page and I want to make its background color transparent. When I do not use the 'background' prop, the background color of el-pagination is white. Here is how it looks: (sorry I can't add an image) htt ...

Ways to ensure child element takes up the entire screen

Here is the layout I am working with: <ul class="all-content white-bg"> <row> <div class="col-md-3"> <!-- Content --> <div class="content white-bg fullscreen clearfix"> < ...

Inaccessible " following the "Return" Conflict

I'm struggling to resolve these warnings: Merge this with the previous "var" statement, found on lines 7, 9 and 10. Unreachable " after 'Return' - it's related to ($window.width() <= 770) { return; Script snippet: //StickyB ...