The issue with the max-height transition not functioning properly arises when there are dynamic changes to the max-height

document.querySelectorAll('.sidebarCategory').forEach(el =>{
      el.addEventListener('click', e =>{
          let sub = el.nextElementSibling
          if(sub.style.maxHeight){
              el.classList.remove('opened')
              sub.style.maxHeight=null
          }
          else{
              document.querySelectorAll('.sidebarSubcategories').forEach(element => {
                  element.style.maxHeight=null
                  element.previousElementSibling.classList.remove('opened')
              })
              el.classList.add('opened')
              sub.style.maxHeight = sub.scrollHeight + "px";
          }
      })
  })
  document.querySelectorAll('.sidebarSubcategories > div:not(.sidebarSubSubcategories)').forEach(el =>{
      el.addEventListener('click', e =>{
          let sub = el.nextElementSibling
          if(sub!=null && sub.classList.contains('sidebarSubSubcategories'))
          {
              if(sub.style.maxHeight){
                  sub.style.maxHeight=null
                  sub.style.marginBottom=0
                  sub.style.padding='0 30px'
              }
              else{
                  sub.style.marginBottom='15px'
                  sub.style.padding='15px 30px'
                  sub.style.maxHeight = sub.scrollHeight + 30 + "px"
                  el.parentNode.style.maxHeight=el.parentNode.style.maxHeight.slice(0,el.parentNode.style.maxHeight.length-2) + sub.scrollHeight + 30 + "px"
              }
          }
      })
  })
.main{
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%,-50%);
      width: 400px;
      height: 300px;
      overflow-y: auto;
      background-color: aquamarine;
  }
  .sidebarCategory{
      color: white;
      position: relative;
      height: 60px;
      min-height: 60px;
      display: flex;
      align-items: center;
      justify-content: flex-start;
      font-size: 20px;
      flex-wrap: wrap;
      font-weight: 600;
      fill: white!important;
      cursor: pointer;
      padding-left: 15px;
      transition: 0.4s;
  }
  .sidebarCategory.opened{
      background-color: rgba(3, 63, 109, 0.588);
  }
  .sidebarSubcategories{
      max-width: 100%;
      position: relative;
      background-color: rgba(3, 63, 109, 0.588);
      max-height: 0;
      transition: 0.4s;
      overflow-y: hidden;
  }
  .sidebarSubcategories > div:not(.sidebarSubSubcategories){
      max-height: 45px;
      /* height: 45px; */
      position: relative;
      min-height: 45px;
      color: white;
      cursor: pointer;
      overflow-y: hidden;
      display: flex;
      align-items: center;
      justify-content: flex-start;
      flex-wrap: wrap;
      padding: 0 30px;
      border-bottom: 1px solid var(--blue);
  }
  .sidebarSubSubcategories{
      max-height: 0;
      overflow-y: hidden;
      transition: 0.4s;
      background-color: white;
      border-radius: 5px;
      display: flex;
      justify-content: center;
      align-items: center;
      flex-wrap: wrap;
      margin: 0 15px;
  }
  .sidebarSubSubcategories > div{
      cursor: pointer;
      transition: 0.2s;
      display: flex;
      justify-content: center;
      border-radius: 5px;
      align-items: center;
      padding: 10px;
      width: 49%;
  }
  .sidebarSubSubcategories > div:hover{
      background-color: #f3f3f3;
  }
<body>
    <div class="main">
        <div class="sidebarCategory">
            Lorem ipsum dolor sit amet.
        </div>
        <div class="sidebarSubcategories">
            <div>
                Subcategory
            </div>
            <div class="sidebarSubSubcategories">
                <div>Sub Subcategory</div>
                <div>Sub Subcategory</div>
                <div>Sub Subcategory</div>
                <div>Sub Subcategory</div>
            </div>
            <div>
                Subcategory
            </div>
            <div>
                Subcategory
            </div>
            <div>
                Subcategory
            </div>
         </div>
     </div>

It appears that the first drop-down does not close smoothly when interacting with the second drop-down menu. This issue arises from nested accordions where changing the max-height property causes a problem in the transition of the outer accordion on interaction with the inner accordion.</p>
    </div></questionbody>
<exquestionbody>
<div class="question">
                
<p><div>
<div>
<pre class="lang-js"><code>document.querySelectorAll('.sidebarCategory').forEach(el =>{
      el.addEventListener('click', e =>{
          let sub = el.nextElementSibling
          if(sub.style.maxHeight){
              el.classList.remove('opened')
              sub.style.maxHeight=null
          }
          else{
              document.querySelectorAll('.sidebarSubcategories').forEach(element => {
                  element.style.maxHeight=null
                  element.previousElementSibling.classList.remove('opened')
              })
              el.classList.add('opened')
              sub.style.maxHeight = sub.scrollHeight + "px";
          }
      })
  })
  document.querySelectorAll('.sidebarSubcategories > div:not(.sidebarSubSubcategories)').forEach(el =>{
      el.addEventListener('click', e =>{
          let sub = el.nextElementSibling
          if(sub!=null && sub.classList.contains('sidebarSubSubcategories'))
          {
              if(sub.style.maxHeight){
                  sub.style.maxHeight=null
                  sub.style.marginBottom=0
                  sub.style.padding='0 30px'
              }
              else{
                  sub.style.marginBottom='15px'
                  sub.style.padding='15px 30px'
                  sub.style.maxHeight = sub.scrollHeight + 30 + "px"
                  el.parentNode.style.maxHeight=el.parentNode.style.maxHeight.slice(0,el.parentNode.style.maxHeight.length-2) + sub.scrollHeight + 30 + "px"
              }
          }
      })
  })
.main{
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%,-50%);
      width: 400px;
      height: 300px;
      overflow-y: auto;
      background-color: aquamarine;
  }
  .sidebarCategory{
      color: white;
      position: relative;
      height: 60px;
      min-height: 60px;
      display: flex;
      align-items: center;
      justify-content: flex-start;
      font-size: 20px;
      flex-wrap: wrap;
      font-weight: 600;
      fill: white!important;
      cursor: pointer;
      padding-left: 15px;
      transition: 0.4s;
  }
  .sidebarCategory.opened{
      background-color: rgba(3, 63, 109, 0.588);
  }
  .sidebarSubcategories{
      max-width: 100%;
      position: relative;
      background-color: rgba(3, 63, 109, 0.588);
      max-height: 0;
      transition: 0.4s;
      overflow-y: hidden;
  }
  .sidebarSubcategories > div:not(.sidebarSubSubcategories){
      max-height: 45px;
      /* height: 45px; */
      position: relative;
      min-height: 45px;
      color: white;
      cursor: pointer;
      overflow-y: hidden;
      display: flex;
      align-items: center;
      justify-content: flex-start;
      flex-wrap: wrap;
      padding: 0 30px;
      border-bottom: 1px solid var(--blue);
  }
  .sidebarSubSubcategories{
      max-height: 0;
      overflow-y: hidden;
      transition: 0.4s;
      background-color: white;
      border-radius: 5px;
      display: flex;
      justify-content: center;
      align-items: center;
      flex-wrap: wrap;
      margin: 0 15px;
  }
  .sidebarSubSubcategories > div{
      cursor: pointer;
      transition: 0.2s;
      display: flex;
      justify-content: center;
      border-radius: 5px;
      align-items: center;
      padding: 10px;
      width: 49%;
  }
  .sidebarSubSubcategories > div:hover{
      background-color: #f3f3f3;
  }
<body>
    <div class="main">
        <div class="sidebarCategory">
            Lorem ipsum dolor sit amet.
        </div>
        <div class="sidebarSubcategories">
            <div>
                Subcategory
            </div>
            <div class="sidebarSubSubcategories">
                <div>Sub Subcategory</div>
                <div>Sub Subcategory</div>
                <div>Sub Subcategory</div>
                <div>Sub Subcategory</div>
            </div>
            <div>
                Subcategory
            </div>
            <div>
                Subcategory
            </div>
            <div>
                Subcategory
            </div>
        </div>
    </div>
</body>
Upon inspection, it seems like the first drop-down encounters an issue while closing smoothly upon interaction with the second drop-down menu. This inconvenience stems from implementing nested accordions using the max-height property, causing a disruption in the transition effect of the external accordion when interacting with the internal one.

Answer №1

It appears that the main issue lies within this particular line of code

el.parentNode.style.maxHeight.slice(0,el.parentNode.style.maxHeight.length-2) + sub.scrollHeight...."

The problem arises from attempting to concatenate a string with a number, resulting in unintended behavior. When you add a number to a string, it will simply combine the two as new string values. To resolve this issue, make sure to convert the string to an integer (you can also omit slicing off the 'px' unit).

//Rather than 
el.parentNode.style.maxHeight.slice(0,el.parentNode.style.maxHeight.length-2)
//Use this approach          
parseInt(el.parentNode.style.maxHeight)

Answer №2

In my analysis, the issue lies in the sidebarSubcategories element lacking a defined height. Initially, it has a max-height set to 0, which is then changed to null using JavaScript.

The default value for height is auto. Therefore, setting maxHeight to null results in the max-height being interpreted as auto, causing transitions not to function correctly on auto values. This occurs because the browser cannot determine the specific value to transition to. If it is imperative for this functionality and manually setting the height of each sidebarSubcategories beforehand is not feasible, one solution could involve storing the innerHeight of each expanded sidebarSubcategories element and reapplying it when it needs to expand again.

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

Styling elements with CSS can sometimes lead to unexpected behavior in Safari on iOS devices, especially

Ever since the release of iOS 14, I've noticed that content within a div element with an 'overflow-y: scroll' property no longer functions properly on Safari. Does anyone happen to have a solution for this? (Or maybe my code just needs some ...

Removing an item from JSON data using Node.js and Express

Currently, I am attempting to remove an entry from json data. In order to view the data, I utilize the following: app.route('/data/:id') .get((req:Request, res: Response) => { let id = req.params.id; res.status(200).send(projects ...

The correct way to reference images in the resources folder using a URL in CSS

After I generated a Maven dynamic web project using an archetype, I decided to organize the javascript, css, and image folders under the webapp folder. The structure now looks like this: myproject | main | | | java | | | resources | | ...

Tips for aligning a row at the bottom within a nested column

Desired Outcome I am struggling to arrange two smaller images next to a larger image using Bootstrap 4. Specifically, I am having difficulty aligning one of the smaller images at the bottom so that it matches the alignment of the larger image. The layout ...

Designing a user interface that consists of numerous distinct components

Challenge I'm faced with a dilemma regarding site A, which is built using React. Specifically, I need to find a way to integrate smaller React components into site A whenever a user navigates to a specific page within the site. Each of these smalle ...

Executing numerous tests on a single response using Node.js along with Chai, Mocha, and Should

I have a setup similar to the one below that allows me to perform a series of API tests using Mocha. While this method works well, it involves making an individual API call for each test. My goal is to streamline the process by utilizing the same API cal ...

Alignment of Bootstrap responsiveness shifted to the left rather than the center

My HTML Code: <div class="gridrow" id="eventsrow"> <div class="gridcard" id="eventcard" style="float:left;width:100%;height:100%;margin-bottom:0.5rem;background-color:white"> <div class="event container"> <div clas ...

What is the best way to activate multiple events within an overlapping area containing multiple divs at the same

How can I trigger events on same level divs that overlap in different areas? When there are multiple divs overlapping, only one of them gets triggered. Is there a way to trigger events on all overlapped same level divs? Here is an example code snippet: ...

When trying to integrate Angular.ts with Electron, an error message occurs: "SyntaxError: Cannot use import statement

Upon installing Electron on a new Angular app, I encountered an error when running electron. The app is written in TypeScript. The error message displayed was: import { enableProdMode } from '@angular/core'; ^^^^^^ SyntaxError: Cannot use impor ...

Utilize jQuery to append YQL output in JSON format to specific IDs in your code

I have a YQL output JSON string at this URL: Check out the YQL JSON here I encountered some other I am exploring why I am facing difficulties in extracting certain items from the returned JSON. For instance, when using jQuery to access the H1 tag within ...

Deselect a checkbox by selecting a radio button with just Javascript code

Hey there! I'm currently delving into the world of pure JavaScript and could really use some guidance on a particular issue. Here's what I'm aiming to accomplish: I'd like to design a checkbox that triggers the opening of a window whe ...

What is the best way to tidy up a function within a useEffect hook?

When updating state within a useEffect hook while using async/await syntax, I encountered an error regarding the cleanup function. I'm unsure how to properly utilize the cleanup function in this scenario. Error: Warning - A React state update was att ...

AngularJS extension known as 'ngclipboard'

I've been attempting to utilize a plugin called ngclipboard in Angular, but something seems amiss as it's not functioning as expected. There are no error messages, however, the text from the input box is not being copied to the clipboard. To see ...

What is the best way to extract a number from a string in JavaScript?

There are instances in HTML files where a <p> tag displays the price of a product, such as ""1,200,000 Dollar"". When a user adds this product to their cart, I want the webpage to show the total price in the cart. In JavaScript, I aim to e ...

The event listener attached to this model is failing to trigger when there are

The issue is that the "change" event is not being triggered in the code snippet below. var PageView = Backbone.View.extend({ el: $("body"), initialize: function(){ this.model.on("change:loading", this.loader, this); }, loader: func ...

putting a division element above a image carousel

Is there a way to overlay a div tag on top of a slideshow, similar to the one shown in this link? In the example provided, a div with the title "DISCOVER THE JOY OF COOKING" is positioned over a slideshow. Any tips on how I can achieve this effect? ...

"Converting to Typescript resulted in the absence of a default export in the module

I converted the JavaScript code to TypeScript and encountered an issue: The module has no default export I tried importing using curly braces and exporting with module.exports, but neither solution worked. contactController.ts const contacts: String[ ...

Maintain parental visibility with children when navigating to a different page

I am currently working on a vertical accordion menu that opens on hover, stays open, and closes when other items are hovered. The great assistance I received from @JDandChips has been instrumental in getting this feature up and running. Now, my main focus ...

Sending an XMLHttpRequest in PHP causes a blank array to be returned

> xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { var jsondata = xmlhttp.responseText; console.log(xmlhttp.responseText); document.getElementById("jsondata").value = js ...

Hover over the hidden DIV

I have a div containing an image that is overlapping multiple other divs. It looks something like this: <div style='width:100%;height:100%'><img src='someImage.png'></div> <div id='covered'>I'm un ...