Adjust the heights of divs dynamically when using slideToggle

Explaining this may be a bit challenging, so please bear with me.

The webpage layout includes a column divided into two panels/sections. The aim is to have the secondary panel expand to occupy the remaining space when one of the panels is minimized.

When Panel 1 is minimized, the list disappears, and Panel 2's header moves up directly below Panel 1 while expanding to fill the rest of the column space.

If Panel 2 is minimized, its list hides, the header goes to the bottom of the page, and Panel 1's list expands to fit the remainder of the column.

Fiddle: http://jsfiddle.net/mL9RG/

Collapsing the lists within the sections using slideToggle works seamlessly. Although incorporating fixed CSS height animations somewhat achieves the desired effect, using percentages for responsiveness has proven challenging.

HTML

<div id="wrapper">
    <div id="section1">
        <h2 id="crossbar1">Section 1<span id="plus2">+/-</span></h2>
        <ul id="list1">
            <li>Stuff</li>
            <li>Stuff</li>
            <li>Stuff</li>
            <li>Stuff</li>
        </ul>
    </div>
    <div id="section2">
        <h2 id="crossbar2">Section 2 <span id="plus2">+/-</span></h2>
        <ul id="list2">
            <li>Stuff</li>
            <li>More Stuff</li>
            <li>Stuff</li>
        </ul>
    </div>
</div>

CSS

#wrapper { width: 200px; height: 400px; margin: 0 auto; background-color: #eaeaea; }
ul { margin: 0; padding: 0; list-style: none; display: block; }
h2 { margin: 0; padding: 5px 0; background-color: #d8d8d8; position: relative; }
h2 span { position: absolute; right: 10px; font-size: 15px; top: 10px; cursor: pointer }
#section1 { 
    height: 50%; width: 100%; background-color: blue;
    box-sizing: border-box;
}
#section2 {
    height: 50%; width: 100%; background-color: green;
}

Jquery

$('#crossbar1').click(function(){
   $('#list1').slideToggle(); 
});
$('#crossbar2').click(function(){
   $('#list2').slideToggle(); 
});

Answer №1

ultimate solution Fiddle

Markup Language

<div class="wrapper">
...
</div>

CSS Styles

.wrapper {
    ...
}

ul { 
    ...
}

h2 { 
    ...
}

h2 span { 
   ...
}

.section {
    ...
}

JavaScript Function

function modifySection(){
    var jq_parent = $(this).closest('.section');
    jq_parent.attr('class', 'section ' + (jq_parent.hasClass('expanded') ? 
                   'collapsed' : 'expanded'));
    var num = $('.expanded').length;
    if (num > 0) {
        var h = (400 - (38 * $('.collapsed').length) )/ num;
        $('.collapsed').animate({height:'38px'});
        $('.expanded').animate({height: h + 'px' });
    }
}
$('.toggle').click(modifySection);
modifySection();

Answer №2

Web Design

<div class="container">
  <div class="item">
    Section 1
    <div class="category"></div>
  </div>
  <div class="content">
      <ul id="list1">
          <li>Content A</li>
          <li>Content B</li>
          <li>Content C</li>
          <li>Content D</li>
      </ul>
  </div>
   <div class="item">
    Section 2
     <div class="category"></div>
  </div>
  <div class="content">
      <ul id="list2">
          <li>More Stuff</li>
          <li>More Stuff</li>
          <li>More Stuff</li>
          <li>More Stuff</li>
      </ul>
  </div>

CSS

body
{
font-family: Arial, Helvetica, sans-serif;
}
.container
{
  width:100%;
  max-height:300px;
  margin:20px auto;
}
.item {
font-size: 1em;
margin: 0 10px 0 10px;
padding: 10px;
height: 20px;
background: #f2f2f2;
border-bottom:1px solid #ccc;
color: #000;
cursor:pointer;
}

.item.active
{
background:#14ad40;
border-bottom:0px;
color:#fff;
}
.item.active .category {
float: right;
background: url('http://vivekarora.com/images/minus.png') center no-repeat;
padding: 10px;
}

.item .category {
float: right;
background: url('http://vivekarora.com/images/plus.png') center no-repeat;
padding: 10px;
}

div.content {
background: #fff;
margin: 0 10px 0 10px;
padding: 10px;
border:1px solid #ccc;
font-size: .8em;
line-height: 140%;
display:none;
}

JavaScript

$(function($) {
  var allContents = $('.container div.content');
  var allItems = $('.container .item');
  $('.container > .item').click(function() {
    if($(this).hasClass('active'))
    {
      $(this).removeClass('active');
      $(this).next().slideUp("slow");
    }
    else
    {
    allContents.slideUp("slow");
    allItems.removeClass('active');
    $(this).addClass('active');
    $(this).next().slideDown("slow");
    return false;
    }
  });
});

VIEW DEMO

Answer №3

Here is a simple solution to achieve your desired outcome.

Using classes instead of IDs can help streamline your code.

HTML

<div id="wrapper">
    <div class="section">
        <h2 class="crossbar">Section 1<span id="plus2">+/-</span></h2>
        <ul id="list1">
            <li>Stuff</li>
            <li>Stuff</li>
            <li>Stuff</li>
            <li>Stuff</li>
        </ul>
    </div>
    <div class="section">
        <h2 class="crossbar">Section 2 <span id="plus2">+/-</span></h2>
        <ul id="list2">
            <li>Stuff</li>
            <li>More Stuff</li>
            <li>Stuff</li>
        </ul>
    </div>
</div>

CSS

#wrapper { width: 200px; height: 400px; margin: 0 auto; background-color: #eaeaea; }
ul { margin: 0; padding: 0; list-style: none; display: block; }
h2 { margin: 0; padding: 5px 0; background-color: #d8d8d8; position: relative; }
h2 span { position: absolute; right: 10px; font-size: 15px; top: 10px; cursor: pointer }
.section{ 
   width: 100%; 
    box-sizing: border-box;
}
#list1{ height: 150px; background-color: blue;}
#list2{ height: 150px; background-color: green;}

Script

$('h2.crossbar').on('click', function(){
    $(this).next('ul').slideToggle();
}); 

Fiddle Demo

Answer №4

From your explanation, it appears that you are referring to the functionality provided by Bootstrap's collapse plugin. Do you think this is accurate? To explore further, you can check out an example at: http://getbootstrap.com/javascript/#collapse

Answer №5

If you're looking to implement flexboxes

It seems like you may have utilized the div#section, but it's not necessary, leading to cleaner markup and fewer nodes in the DOM:

<div id="wrapper">
    <h2 id="crossbar1">Section 1<span id="plus1">+/-</span></h2>
    <ul id="list1">
        <li>Stuff</li>
        <li>Stuff</li>
        <li>Stuff</li>
        <li>Stuff</li>
    </ul>
    <h2 id="crossbar2">Section 2 <span id="plus2">+/-</span></h2>
    <ul id="list2">
        <li>Stuff</li>
        <li>More Stuff</li>
        <li>Stuff</li>
    </ul>
</div>

We can now make use of #wrapper as a flexbox (with display: flex) in a column layout (flex-direction: column), causing the content to be distributed vertically. Additionally, we set the flex-grow on the lists to 1 so they can expand if needed:

#wrapper { display: flex; flex-flow: column nowrap; 
           width: 200px; height: 400px; margin: 0 auto; background-color: #eaeaea; }
#wrapper > ul { flex-grow:1; margin: 0; padding: 0; list-style: none; }

/* your old rules */
h2 { margin: 0; padding: 5px 0; background-color: #d8d8d8; position: relative; }
h2 span { position: absolute; right: 10px; font-size: 15px; top: 10px; cursor: pointer }

#list1{background-color: blue}
#list2{background-color: green}

I've implemented an approach for mutual behavior that can easily accommodate more sections:

var addToToggleGroup = (function(){
    var toggleState = []; // holds the state of the elements in the group

    var toggle = function(i, target) {
        toggleState[i] = !toggleState[i];

        // prevent toggling the last element

        if(toggleState.every(function(el){ return !el;})){
            toggleState[i] = !toggleState[i];
            return;
        } else {
            $(target).slideToggle();
        }
    }

    return function (el, target){
        var i = toggleState.length;
        toggleState.push(true);
        $(el).on("click", function(){
            toggle(i, target);
        })
    }
})();

// add elements to the toggle group using jQuery selectors
addToToggleGroup("#crossbar1","#list1");
addToToggleGroup("#crossbar2","#list2");

That concludes it (fiddle).

References

Answer №6

My recommendation is to utilize jQuery's .toggleClass() method.

If you define two additional classes:

.open-box {
    height: 50%;    
}

.expanded-box {
    height: 100%;   
}

You can then manage the content box states like this:

$('#switch1').click(function(){
   $("#boxOne").toggleClass('open-box', 100);
   $('#contentOne').slideToggle(100); 
   $("#boxTwo").toggleClass('expanded-box', 100);   
});

$('#switch2').click(function(){
   $("#boxTwo").toggleClass('open-box', 100);
   $('#contentTwo').slideToggle(100); 
   $("#boxOne").toggleClass('expanded-box', 100);    
});

This approach functions flawlessly and achieves the intended outcome.

VIEW DEMO

You can also accomplish this by explicitly tracking the boxes' states:

DEMO 2

I hope this solution proves beneficial for your needs!

Answer №7

Review my customized solution for animating the height feature. The expected outcome should resemble your visual references.

Adjusted css:

#wrapper { 
    width: 200px; height: 400px; margin: 0 auto; background-color: #eaeaea; 
    position: relative;
}
ul { margin: 0; padding: 0; list-style: none; display: block; }
h2 { margin: 0; padding: 5px 0; background-color: #d8d8d8; position: relative; }
h2 span { position: absolute; right: 10px; font-size: 15px; top: 10px; cursor: pointer }

#section1, #section2{
    box-sizing: border-box;
    width: 100%;
    height: 50%;
}

#section1 { 
    background-color: blue;
}
#section2 {
    background-color: green;
} 

Modified js

$('#crossbar1').click(function(){
    if($('#list1').is(':hidden')){
        if($('#list2').is(':hidden')){
            $( "#section1" ).animate({height: "362px"});
            $( "#section2" ).animate({height: "37px"});
        }else{   
            $( "#section1" ).animate({height: "50%"}); 
            $( "#section2" ).animate({height: "50%"});    
        } 
    }else{   
        if($('#list1').is(':hidden')){
            $( "#section1" ).animate({height: "362px"});
        }else{   
            $( "#section1" ).animate({height: "37px"}); 
            $( "#section2" ).animate({height: "362px"});     
        }  
    }
    $('#list1').slideToggle(); 
});
$('#crossbar2').click(function(){
    if($('#list2').is(':hidden')){  
        if($('#list1').is(':hidden')){
            $( "#section2" ).animate({height: "362px"});
        }else{   
            $( "#section2" ).animate({height: "50%"});
            $( "#section1" ).animate({height: "50%"});     
        } 
    }else{   
        if($('#list1').is(':hidden')){
            $( "#section2" ).animate({height: "362px"});
        }else{   
            $( "#section2" ).animate({height: "37px"}); 
            $( "#section1" ).animate({height: "362px"});     
        }  
    }
    $('#list2').slideToggle(); 
});

Experience the demonstration on jsFiddle. Hopefully, this aligns with your expectations.

Edit: Addressed a minor glitch by adjusting section2 first before toggling section1. (Updated jsFiddle-Demo)

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

Creating a responsive design for an absolutely positioned element

Currently, I am working on an image slider that features two arrow keys. The issue arises when I attempt to adjust the viewport to a smaller size. While the image slider responds by changing its size accordingly, the arrow keys do not follow suit. I am uns ...

Error: Attempting to insert or update the "tokens" table violates the foreign key constraint "tokens_userId_fkey" in Sequelize

I am facing an issue that I can't seem to resolve, as I keep encountering an error related to a constraint violation. The tables involved in this problem are Token and User, which are linked through the userId column. The error occurs when I try to cr ...

What could be the reason behind the error message "Java heap space exception in Eclipse" appearing while trying to use JavaScript autocomplete?

Whenever I attempt to utilize a JavaScript template on Eclipse, the program always freezes, displaying an error message stating: "Unhandled event loop exception Java heap space." To troubleshoot this issue, I initiated a top command in Ubuntu for both the ...

What is the best way to implement a decorator for a class method variable within a NestJS framework?

import {isNotEmpty} from "class-validator"; export Service { create(createdto) { const {name,age} = createdto; @isNotEmpty() name //applying a decorator to ensure name is not null or undefined } } As the decorator is designed for ...

Search for new nodes asynchronously in jsTree to trigger loading them

I am currently using jsTree in a project and everything is running smoothly. The JSON data is being supplied by PHP/Ajax, but I'm encountering some difficulties with the search plugin. The documentation for jsTree's search plugin states: "so ...

Quantity display issue in jQuery list

As someone who is new to jQuery and coding in general, I have spent several days working on a shopping list App using jQuery. While I have made progress, there are two specific issues that I am struggling with. The quantity selector has been successfully ...

Utilizing the summernote editor in combination with vue.js 2

Integrating Summernote into a Vue.js 2 single-page application has been quite a challenge for me. Not all my pages require the Summernote editor, so I decided to turn it into a component by creating an export function in my Vue file. export default { ...

Breaking Down An Array of Objects Using JavaScript

I am facing an issue with splitting/separating objects within an array. I know how to do it for a single object, but the challenge arises when dealing with an array of objects. The array structure is as follows: [ { "KPI": "Produ ...

the division does not span the entire width

I am faced with a dilemma involving two div elements structured as follows: <div id="left"><p>.....</p><br/> <p>.....</p> </div> <div id="right"><img ..../></div> Accompanied by CSS styling: #l ...

When pasting content that exceeds a certain height, Quill will automatically scroll to the top on webkit-based browsers such as Chrome

This was my original query here I've been attempting to recreate the auto-grow functionality showcased in their interactive playground My approach involved adding a scrolling container and setting specific heights for elements, however, You can als ...

Tips for making li elements scroll horizontally whilst fitting all elements on one line exclusively using CSS

I am attempting to alter the default scrolling behavior of li elements from vertical to horizontal in HTML. I have successfully achieved this, but the output displays a succession of lists in a line, followed by another list below it. However, I desire to ...

Centralized Bootstrap Contact Form Design

I am currently in the process of setting up a contact form and my goal is to have this form centered on my webpage. However, I do not want it to take up the full width (col-md-12) of the page. Instead, I would like it to be the width of a col-md-6 located ...

Is there a more efficient or concise way to phrase this?

To simplify my jsfiddle project, I am trying to create a path that loops a certain number of times based on user input. For example, if the user enters a number less than 30, one path (a bottle) will be drawn on the paper. If the number is above 30, two pa ...

Retrieving the first five rows from a table with data entries

My task involves working with a table named mytbl, which contains 100 rows. I need to extract only the first five rows when a user clicks on "Show Top Five." Although I attempted the following code, the alert message returned 'empty': var $upda ...

Locating Mongoose users who have registered within specific date ranges

My user model looks like this const guestSchema = mongoose.Schema({ facebook: { id: String, token: String, email: String, name: String, phone: String, dates: [ { type: mongoose.Schema.Types.ObjectId, ref: "l ...

Safari's approach to image height measurement

I am experiencing an issue with some images in Safari. While they display correctly on other browsers, the images are appearing too high on Safari. You can view the website at development.mar-bakker.nl <div class="col-xs-12 col-sm-4 col-md-4"> ...

Having an iframe at the bottom of the page is causing unnecessary white space below the

I currently have an iframe placed in the footer of my website. When I try to set the height of the iframe to match the height of the footer, it results in unwanted white space appearing below the iframe. The issue can be seen here: JSFiddle To fix this p ...

Selenium's ByChained, By.CssSelector, By.XPath, and ByJQuery.ByJQuerySelector are not meeting my expectations in terms of functionality

I'm struggling with identifying a specific selector. My NUnit test keeps failing when it reaches the selector. I need some assistance to correct this issue. Let's dive into an example. Here is the HTML code: <div class="form-item required ro ...

The promise is throwing an error stating that it cannot read the property 'code' of undefined when using the context api in React hooks

I'm currently working on developing my first hybrid web app using React Hooks. I've encountered a timing issue involving promises and the Context API. Here's the challenge I'm dealing with. A function called fetchApplications retrieve ...

Aligning a div with absolute positioning vertically

There are two elements positioned side by side: an input field and a div. The div is absolutely positioned inside a relative element and placed to the right of the input. The input field has a fixed height, while the height of the div depends on its conte ...