Search code examples
htmlcssbootstrap-4accordionbootstrap-accordion

Getting the accordion to take full height and each individual panes to take the full viewport height. (Bootstrap 4)


https://i.sstatic.net/LqhXn.png This doesn't belong to me but its clear to explain what I want to achieve.

Below is my current code

<div class="accordion" id="myAccordion">
          <div class="card">
            <div class="card-header" id="section1" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
              <h2 class="mb-0">
                <i class="fa fa-search" aria-hidden="true"></i> Section 1
              </h2>
            </div>
        
            <div id="collapseOne" class="collapse" aria-labelledby="section1" data-parent="#myAccordion">
              <div class="card-body">
                Some content here
              </div>
            </div>
          </div>

          <div class="card">
            <div class="card-header" id="section2" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
              <h2 class="mb-0">
                 <i class="fa fa-briefcase" aria-hidden="true"></i> Section 2
              </h2>
            </div>
            <div id="collapseTwo" class="collapse" aria-labelledby="section2" data-parent="#myAccordion">
              <div class="card-body">
                some other content here
              </div>
            </div>
          </div>
            </div>
          </div>
        </div>

I've look at some similar questions asked and none has helped by far. I need the the card-body of section1 to take full height based on the user's viewpoint despite the amount of content inside the card-body, and push section2's card-header all the way to the bottom of the accordion. Any help or further reference is appreciated.

[This is what the result I have now ->] https://i.sstatic.net/THCb9.png


Solution

  • The basic idea is to set the accordion height to 100% viewport height, display the accordion as flexbox in column direction, and grow the opened section (using flex-grow:1;) so that it will take up the remaining space vertically.

    This way you don't have to hard code any number for heights.

    It would have been PURE CSS if Bootstrap has the ability to extend the collapse plugin so that I can add any CSS class to the parent who has a collapsible child. Currently when you click on the header, the collapsible section opens and the .show class is only added to that collapsible section, not its parent .card.


    To identity which .card is open we need the following JavaScript utilizing Bootstrap Collapse Events:

    $(function() {
        $('.accordion-vh-100 .collapse').on('show.bs.collapse', function () {
            $(this).parents('.card').addClass('show');
        });
        
        $('.accordion-vh-100 .collapse').on('hide.bs.collapse', function () {
            $(this).parents('.card').removeClass('show');
        });
    });
    

    Here when we toggle the collapsible, I add/remove a CSS class .show on its parent .card.

    Now we know which .card is opened when its collasible child is opened. We can start writing CSSs to make the accordion take up 100% viewport height.


    First, I would like to introduce a separate CSS class for this 100% viewport height feature. Let's call it .accordion-vh-100. Another change I made was to change the .card-header from a div to an anchor tag so that the entire .card-header is clickable:

    <div class="accordion accordion-vh-100" id="myAccordion">
        <div class="card">
            <a class="card-header" href="#collapseOne" data-toggle="collapse">
                <h2 class="mb-0">Section 1</h2>
            </a>
            <div id="collapseOne" class="collapse" data-parent="#myAccordion">
                <div class="card-body">...</div>
            </div>
        </div>
        ...
    </div>
    

    Next, we need to style the new .accordion-vh-100 to take up 100% viewport height, as well as to display as a flexbox with a column flow direction:

    .accordion-vh-100 {
        height: 100vh;
        display: flex;
        flex-flow: column nowrap;
    }
    

    Lastly, we need to grow the opened .card:

    .accordion-vh-100 .card.show {
        flex-grow: 1;
    }
    

    enter image description here


    demo: https://jsfiddle.net/davidliang2008/b1duyLs8/24/