Why can't we use percentages to change the max-height property in JavaScript?

I am currently working on creating a responsive menu featuring a hamburger icon. My goal is to have the menu list slide in and out without using jQuery, but instead relying purely on JavaScript.

HTML :

<div id="animation">  
</div>
<button id="toggle">Toggle</button>

CSS :

div {
width: 300px;
height: 300px;
background-color: blue;
}

Javascript :

var but = document.getElementById('toggle');
var div = document.getElementById('animation');
var animate = function(type, callback){
var inter = -1, start = 100, end = 0;
if(type==true){
    inter = 1;
    start = 0;
    end = 100;
}
var si = setInterval(function(){
    console.log('maxheight');
    div.style.maxHeight = (start + inter) + '%';
    if(start == end){
        clearInterval(si);
    }
}, 10);
}

var hidden = false;
but.onclick = function(){
animate(hidden, function(){
    hidden = (hidden == false) ? true : false;
});
}

div.style.maxHeight = "50%";

Answer №1

The issue arises from the fact that for proportional height in an element to work properly, a fixed height needs to be set on the parent element. However, in your case, no parent with a fixed height has been provided since the maxHeight property also relies on a percentage value based on the parent element.

To resolve this, you need to enclose your div within a parent container that has a fixed height. Here is the corrected version of your code:

var button = document.getElementById('toggle');
var container = document.getElementById('animation');
var animate = function(type, callback) {
  var interval = -1,
    startPercentageValue = 100,
    endPercentageValue= 0;
  if (type) {
    interval = 1;
    startPercentageValue = 0;
    endPercentageValue = 100;
  }
  var si = setInterval(function() {
    console.log('maxheight');
    container.style.maxHeight = (startPercentageValue + interval) + '%';
    if (startPercentageValue == endPercentageValue) {
      clearInterval(si);
    }
  }, 10);
}
var hidden = false;

button.onclick = function() {
  animate(hidden, function() {
    hidden = !hidden ;
  });
}

container.style.maxHeight = "50%";
#animation {
  width: 300px;
  height: 300px;
  background-color: blue;
}
#parent {
  width: 500px;
  height: 500px;
}
<div id="parent">
  <div id="animation">
  </div>
  <button id="toggle">Toggle</button>
</div>

Note:

It should be noted that there are certain statements in your JavaScript code that require modification:

if(type==true) can be simplified to if(type).

hidden = (hidden == false) ? true : false;
can be shortened to hidden = !hidden

Answer №2

It appears that there are some errors in your code that I have addressed. I have made adjustments to the JavaScript and added comments to clarify the changes I made.

var button = document.getElementById('toggle');
var targetDiv = document.getElementById('animation');
var animateToggle = function (type, callback) {
  var start = 100,
      end = 0;

  if (type) {
    start = 0;
    end = 100;
  }

  var intervalId = setInterval(function () {
    if (type) { 
      start++;
    } else {
      start--
    }

    targetDiv.style.maxHeight = start + '%';

    if (start == end) {
      clearInterval(intervalId);
    }
  }, 10);

  callback.call(this); 
}

var isHidden = false;
button.onclick = function () {
  animateToggle(isHidden, function () {
    isHidden = !isHidden; 
  });
}
/*make sure parent container has a height set or max height won't work*/
html, body {
    height:100%;
    margin:0;
    padding:0;
} 
div {
    width: 300px;
    height: 300px;
    background-color: blue;
}
<div id="animation"></div>
<button id="toggle">Toggle</button>

Example Fiddle

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

JavaScript's getElementsByName() method allows for easy access and

Excuse my lack of experience... I am attempting to run a javascript using the getElementByName method, with the goal of entering 0 in the quantity field on a particular site after 15 seconds of arriving there. Upon inspecting the quantity field, here is w ...

Alert: It is invalid for an <a> element to be nested inside another <a> element according to validateDOMNesting

I've been experimenting with using react-router in conjunction with reactstrap and create-react-app. While setting up the routing within my application, I encountered a need to utilize state for the reactstrap components. To achieve this, I converted ...

What is the best way to switch the CSS style of a button that has been mapped

I'm currently working on toggling the CSS class for an individual button that is created from a mapped array. Although my code is functional, it toggles the CSS class for all buttons in the mapped array instead of just the one selected. ...

Get rid of the strange border on the material dialog

I am struggling with the Angular material 6 dialog component as it is displaying a strange border. I have attempted to remove it using the code below, without success. Interestingly, when I apply the style inline in the browser, it works fine. Any suggesti ...

Creating a reusable field for reactive forms in Angular: A step-by-step guide

I need assistance with creating a versatile field component for reactive forms, but I am facing challenges in retrieving the value from the custom-input element. <form [formGroup]="form" (ngSubmit)="submit()"> <custom-input i ...

Notifying the view with a SignalR message from the controller upon event trigger

Just starting out with SignalR and attempting to set up a notification for a specific event triggered by an API. What I've attempted: Hub: public class NotificationHub : Hub { private static IHubContext hubContext = GlobalHost.Connectio ...

Move an object in relation to the right boundary of the viewport

I have a div that starts off the screen due to this CSS code: transform: translateX(100%); Now, I am looking to bring this div back into view by a specific distance from the right side. Although I have tried using transform: translateX(-450px), it seems ...

Why is my code throwing an error stating "Unable to assign value to innerHTML property of null"?

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title> </head> <body> <div class="container">Lorem ipsum</div&g ...

Guide to transforming the image's color with CSS3

Is there a way to transform the color of an image from grayscale to green, red, or yellow using CSS3? I attempted the code below but unfortunately, it did not produce the desired result. img { -webkit-filter: hue-rotate(90deg); filter: hue-rotat ...

Troubleshooting tip for React JS: encountered an unexpected object error when trying to import components

I've been working on building a react app with Create React App, and everything was going smoothly until I encountered a frustrating error message: Element type is invalid: expected a string (for built-in components) or a class/function (for composite ...

Executing jQuery post request on a div loaded via ajax

I'm facing a challenge with my webpage. I have a section where the content of a div is loaded via ajax. This div contains forms, and after submission, it should update to display the new content without refreshing the entire page. Can anyone guide me ...

Menu navigation - ensuring the background color extends to cover the entire page, not just the viewport

I'm facing an issue with the left navigation bar's design. Specifically, I'd like the grey color of the bar to extend vertically across the entire page. Currently, the gray bar ends at the viewport's edge. Is there a way to make the ba ...

Employing lodash for object comparison and removal from an array

In my current project, I am using lodash to compare two arrays of objects and extract the differences between them. The goal is to add this difference to the original data set while maintaining the existing data intact. For instance, if there are initially ...

Tips on configuring HTTP headers for numerous messages within Node-RED?

I've been working on a flow that involves breaking down a large message into smaller messages. I've successfully implemented the logic for splitting the message, but when attempting to send these small messages to an http response node, I encount ...

Converting Epoch timestamp to AM/PM format in a React render function

I am currently working on a personal project using React.js. I have successfully fetched an API, and one of the values returned is an Epoch timestamp. My goal is to display this timestamp in a human-readable format such as am/pm. The Epoch timestamp is dis ...

Personalized 404 Error Page on Repl.it

Is it possible to create a custom 404-not found page for a website built on Repl.it? I understand that typically you would access the .htaccess file if hosting it yourself, but what is the process when using Repl.it? How can I design my own 404-not found p ...

What are some strategies for keeping the focus state on the parent item in a dropdown menu?

When I interact with the dropdown menu in my navigation bar, the color changes for the child items. How can I make sure that the parent item maintains the same colored background even after clicking elsewhere on the page? To better understand the issue, i ...

What is the best way to implement individual fade-ins for each image in my project?

Regular Whenever I hover over one image, all images fade together. I'm not sure how to prevent this effect from occurring simultaneously. Any assistance would be greatly appreciated. Link to my stylesheet Link to my index page I have attempted to f ...

Tips for choosing the initial paragraph within a div that has a designated class (CSS 2)

I have a <div> that contains multiple <p> elements, and I want to apply specific styling only to the first <p> within each <div> with a unique class called cnt. Please take note that this question may seem similar to others on SO, ...

Contrast the differences between arrays and inserting data into specific index positions

In this scenario, I have two arrays structured as follows: arr1=[{room_no:1,bed_no:'1A'}, {room_no:1,bed_no:'1B'}, {room_no:2,bed_no:'2A'}, {room_no:3,bed_no:'3A'}, {room_no:3,bed_no:'3B ...