Bootstrap: Collapse other sections when one is expanded

Twitter BootstrapCollapse

Twitter Bootstrap Problem Overview


I am making a Rails app, and am trying to achieve a particular functionality relating to Twitter's Bootstrap collapse. Bear with me as I explain it.

I currently have the following view:

enter image description here

When each of these buttons is clicked, their data-toggle div is expanded. The view is set-up as follows:

	<button class="btn dropdown" data-toggle="collapse" data-target="#keys"><i class="icon-chevron-right"></i> Keys <span class="badge badge-info pull-right"><%= @app.keys.count %></span></button>
    <button class="btn dropdown" data-toggle="collapse" data-target="#attrs"><i class="icon-chevron-right"></i> Attributes</button>
	<button class="btn dropdown" data-toggle="collapse" data-target="#edit"><i class="icon-chevron-right"></i> Edit Details</button>
	
	<div class="collapse indent" id="keys">
		<!--content-->
	</div>

	<div class="collapse indent" id="attrs">
		<!--content-->
	</div>
    
	<div class="collapse" id="edit">
		<!--content-->
	</div>

I have them set-up like this, because I want the buttons side by side, in a row. If I move the buttons to be right above the view they expand/collapse, then the buttons stack on top of one another.

So, my end goal is to have the three buttons side-by-side and have them collapse and expand their respective sections. The current set-up works, however is a little awkward. For example, if someone expands the keys section and then expands the attributes section, they have to scroll below the keys section.

There are two possible solutions to this problem. One is that pressing one button causes the other 2 to collapse themselves. This would mean that at any given time, only one of these sections is expanded.

The better solution, I think would be to have it so that when keys is expanded, the buttons to the right move down to the bottom of the keys div, and when attributes is expanded, the edit details button moves to the bottom of that div. Is this possible? I have already tried to do it by letting the buttons stack on top of each other and changing their relative locations through css, but that didn't work because when one of the sections was expanded, the other buttons ended up in awkward spots in the middle of the expanded section.

Lastly, I would like to try to do this without the accordion style behavior as mentioned on twitter's bootstrap page, but if someone can convince me from a design standpoint that it is preferable, I would certainly reconsider.

Twitter Bootstrap Solutions


Solution 1 - Twitter Bootstrap

Using data-parent, first solution is to stick to the example selector architecture

<div id="myGroup">
    <button class="btn dropdown" data-toggle="collapse" data-target="#keys" data-parent="#myGroup"><i class="icon-chevron-right"></i> Keys  <span class="badge badge-info pull-right">X</span></button>
    <button class="btn dropdown" data-toggle="collapse" data-target="#attrs" data-parent="#myGroup"><i class="icon-chevron-right"></i> Attributes</button>
    <button class="btn dropdown" data-toggle="collapse" data-target="#edit" data-parent="#myGroup"><i class="icon-chevron-right"></i> Edit Details</button>
    
    <div class="accordion-group">
        <div class="collapse indent" id="keys">
            keys
        </div>
    
        <div class="collapse indent" id="attrs">
            attrs
        </div>
    
        <div class="collapse" id="edit">
            edit
        </div>
    </div>
</div>

Demo (jsfiddle)

Second solution is to bind on the events and hide the other collapsible elements yourself.

var $myGroup = $('#myGroup');
$myGroup.on('show.bs.collapse','.collapse', function() {
    $myGroup.find('.collapse.in').collapse('hide');
});

Demo (jsfiddle)

PS: the strange effect in the demos is caused by the min-height set for the example, just ignore that.


Edit: changed the JS event from show to show.bs.collapse as specified in Bootstrap documentation.

Solution 2 - Twitter Bootstrap

If you don't want to change your markup, this function does the trick:

jQuery('button').click( function(e) {
	jQuery('.collapse').collapse('hide');
});

Whenever a BUTTON is clicked, all sections become collapsed. Then bootstrap opens the one you selected.

Solution 3 - Twitter Bootstrap

> For Bootstrap v5

Add the data-bs-parent attribute to the collapse elements. Thanks to @Diana for the update. > For Bootstrap v4.1

Add the data-parent attribute to the collapse elements instead on the button.

<div id="myGroup">
<button class="btn dropdown" data-toggle="collapse" data-target="#keys"><i class="icon-chevron-right"></i> Keys  <span class="badge badge-info pull-right">X</span></button>
<button class="btn dropdown" data-toggle="collapse" data-target="#attrs"><i class="icon-chevron-right"></i> Attributes</button>
<button class="btn dropdown" data-toggle="collapse" data-target="#edit"><i class="icon-chevron-right"></i> Edit Details</button>

<div class="accordion-group">
    <div class="collapse indent" id="keys"  data-parent="#myGroup">
        keys
    </div>

    <div class="collapse indent" id="attrs"  data-parent="#myGroup">
        attrs
    </div>

    <div class="collapse" id="edit"  data-parent="#myGroup">
        edit
    </div>
</div>

Solution 4 - Twitter Bootstrap

If you are using Bootstrap 4, and you don't want to change your markup:

var $myGroup = $('#myGroup');
$myGroup.on('show.bs.collapse','.collapse', function() {
$myGroup.find('.collapse.show').collapse('hide');
});

Solution 5 - Twitter Bootstrap

Bootstrap 3 example with side by side buttons below the content

.panel-heading {
  display: inline-block;
}

.panel-group .panel+.panel {
  margin: 0;
  border: 0;
}

.panel {
  border: 0 !important;
  -webkit-box-shadow: none !important;
  box-shadow: none !important;
  background-color: transparent !important;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>


<div class="panel-group" id="accordion">
    <div class="panel panel-default">
        <div id="collapse1" class="panel-collapse collapse in">
            <div class="panel-body">Lorem ipsum dolor sit amet, consectetur adipisicing elit,
        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
        </div>
    </div>
    <div class="panel panel-default">
        <div id="collapse2" class="panel-collapse collapse">
            <div class="panel-body">Lorem ipsum dolor sit amet, consectetur adipisicing elit,
        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
        </div>
    </div>
    <div class="panel panel-default">
        <div id="collapse3" class="panel-collapse collapse">
            <div class="panel-body">Lorem ipsum dolor sit amet, consectetur adipisicing elit,
        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
        </div>
    </div>
</div>
<div class="panel-heading">
    <h4 class="panel-title">
        <a data-toggle="collapse" data-parent="#accordion" href="#collapse1">Collapsible Group 1</a>
    </h4>
</div>
<div class="panel-heading">
    <h4 class="panel-title">
        <a data-toggle="collapse" data-parent="#accordion" href="#collapse2">Collapsible Group 2</a>
    </h4>
</div>
<div class="panel-heading">
    <h4 class="panel-title">
        <a data-toggle="collapse" data-parent="#accordion" href="#collapse3">Collaple Group 3</a>
    </h4>
</div>

Bootstrap 3 example with side by side buttons above the content

.panel-heading {
  display: inline-block;
}

.panel-group .panel+.panel {
  margin: 0;
  border: 0;
}

.panel {
  border: 0 !important;
  -webkit-box-shadow: none !important;
  box-shadow: none !important;
  background-color: transparent !important;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

<div class="panel-heading">
    <h4 class="panel-title">
        <a data-toggle="collapse" data-parent="#accordion" href="#collapse1">Collapsible Group 1</a>
    </h4>
</div>
<div class="panel-heading">
    <h4 class="panel-title">
        <a data-toggle="collapse" data-parent="#accordion" href="#collapse2">Collapsible Group 2</a>
    </h4>
</div>
<div class="panel-heading">
    <h4 class="panel-title">
        <a data-toggle="collapse" data-parent="#accordion" href="#collapse3">Collaple Group 3</a>
    </h4>
</div>
<div class="panel-group" id="accordion">
    <div class="panel panel-default">
        <div id="collapse1" class="panel-collapse collapse in">
            <div class="panel-body">Lorem ipsum dolor sit amet, consectetur adipisicing elit,
        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
        </div>
    </div>
    <div class="panel panel-default">
        <div id="collapse2" class="panel-collapse collapse">
            <div class="panel-body">Lorem ipsum dolor sit amet, consectetur adipisicing elit,
        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
        </div>
    </div>
    <div class="panel panel-default">
        <div id="collapse3" class="panel-collapse collapse">
            <div class="panel-body">Lorem ipsum dolor sit amet, consectetur adipisicing elit,
        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
        </div>
    </div>
</div>

Solution 6 - Twitter Bootstrap

If you stick to HTML structure and proper selectors according to the Bootstrap convention, you should be alright.

<div class="panel-group" id="accordion">
	<div class="panel panel-default">
	  <div class="panel-heading">
	    <h4 class="panel-title">
	      <a data-toggle="collapse" data-parent="#accordion" href="#collapse1">Collapsible Group 1</a>
	    </h4>
	  </div>
	  <div id="collapse1" class="panel-collapse collapse in">
	    <div class="panel-body">Lorem ipsum dolor sit amet, consectetur adipisicing elit,
	    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
	    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
	  </div>
	</div>
	<div class="panel panel-default">
	  <div class="panel-heading">
	    <h4 class="panel-title">
	      <a data-toggle="collapse" data-parent="#accordion" href="#collapse2">Collapsible Group 2</a>
	    </h4>
	  </div>
	  <div id="collapse2" class="panel-collapse collapse">
	    <div class="panel-body">Lorem ipsum dolor sit amet, consectetur adipisicing elit,
	    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
	    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
	  </div>
	</div>
	<div class="panel panel-default">
	  <div class="panel-heading">
	    <h4 class="panel-title">
	      <a data-toggle="collapse" data-parent="#accordion" href="#collapse3">Collapsible Group 3</a>
	    </h4>
	  </div>
	  <div id="collapse3" class="panel-collapse collapse">
	    <div class="panel-body">Lorem ipsum dolor sit amet, consectetur adipisicing elit,
	    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
	    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
	  </div>
	</div>
</div> 

DEMO

Solution 7 - Twitter Bootstrap

In bootstrap 4 to close all collapseds works like this:

ACTION:

<button id="CloseAll" class="btn btn-primary" type="button" data-toggle="collapse">Close All</button>

JQUERY:

$(document).ready(function() {
    $("#CloseAll").on('click', function() {
        $(".collapse").removeClass("show");
    });
});

Solution 8 - Twitter Bootstrap

Use this:

$('.panel-defaul.ph').on('show.bs.collapse', function () {
    $(this).children('.panel-heading').addClass('panel-heading-collapsed');  
    $('.panel-defaul.ph').not(this).children('.panel-collapse').removeClass('in');
}); 

Solution 9 - Twitter Bootstrap

working like a charm here for bootstrap 4>4.1.1

var myGroup = $('your-list');

myGroup.on('show.bs.collapse','.collapse', function() {
   myGroup.find('.collapse.show').collapse('hide');
});

Solution 10 - Twitter Bootstrap

This was helpful for me:

    jQuery('button').click( function(e) {
    jQuery('.in').collapse('hide');
});

It's collapsed already open section. Thnks to GrafiCode Studio

Solution 11 - Twitter Bootstrap

On Bootstrap5

Like noticed in the docu you can use the "data-bs-parent=.." attribute

If parent is provided, then all collapsible elements under the specified parent will be closed when this collapsible item is shown. (similar to traditional accordion behavior - this is dependent on the card class). The attribute has to be set on the target collapsible area.

see more in bootstrap5 docu

Solution 12 - Twitter Bootstrap

The Method Works Properly For me:

var lanopt = $(".language-option");

lanopt.on("show.bs.collapse",".collapse", function(){
   lanopt.find(".collapse.in").collapse("hide");
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionfiniteloopView Question on Stackoverflow
Solution 1 - Twitter BootstrapSherbrowView Answer on Stackoverflow
Solution 2 - Twitter BootstrapGrafiCodeView Answer on Stackoverflow
Solution 3 - Twitter BootstrapJuan Carlos IbarraView Answer on Stackoverflow
Solution 4 - Twitter BootstrapAbermView Answer on Stackoverflow
Solution 5 - Twitter BootstrapFrank GrootView Answer on Stackoverflow
Solution 6 - Twitter BootstrapcptstarlingView Answer on Stackoverflow
Solution 7 - Twitter BootstrapDhellView Answer on Stackoverflow
Solution 8 - Twitter BootstrapMurat SATIRView Answer on Stackoverflow
Solution 9 - Twitter BootstrapVitor PiovezamView Answer on Stackoverflow
Solution 10 - Twitter BootstrapPavel L.View Answer on Stackoverflow
Solution 11 - Twitter Bootstraprelo80View Answer on Stackoverflow
Solution 12 - Twitter BootstrapRubel HossainView Answer on Stackoverflow