davidpauljunior
davidpauljunior

Reputation: 8338

jQuery set height on a sibling when clicked

Earlier I asked this question about setting a height back to 0 after toggling a class.

Whilst the answer was correct, it turned out my question was not so I'm back to rephrase and try and solve my problem.

enter image description here

The HTML is like this:

<li class="slidedown">
  <a href="#">Parent Link</a>
  <!-- Dropdown arrow -->
  <span class="slidedown-toggle">
    <span class="caret"></span>
  </span>
  <!-- Submenu -->
  <ul class="nav nav-sub">
    <li>
      <a href="#">Child Menu Item 1</a>
    </li>
  </ul>
</li>

The answer to my previous question gave me this script:

$(function navCollapse() {

  var slidedownToggle = $('#global-nav .slidedown-toggle');

  slidedownToggle.click(function () {
    var slidedown = $(this).parent('.slidedown');
    var $li = $(this).closest('li');
    var subnav = $(this).siblings('.nav-sub');
    var subnavHeight = subnav.height();

    slidedown.toggleClass('open');

    if ($li.hasClass('open')) {
        subnav.height(0);
    } else {
        subnav.height(subnavHeight);
    }

  });

});

BUT I quickly realised that once the height had been set to 0, the script would continue to calculate it as 0 from then on, no matter how many times you click. Which leaves me stuck and confused.

The old Bootstrap Collapse is pretty much what I want (only the height change). It sets the height via JavaScript and then uses CSS to do the transition. Although I'd prefer not to have my sub-menu have display: none.

Any ideas?

NOTE: I don't want to use JavaScript animations. I want to use CSS for that. I also don't want to use the max-height solution to CSS only dropdowns. That is my fallback.

DEMO

Upvotes: 1

Views: 602

Answers (2)

Bryan Gentry
Bryan Gentry

Reputation: 873

Here is one way: http://jsfiddle.net/Tes9P/2/

Basically, this applies the transition to a wrapper div that goes around the sub menu. Because CSS transitions require a set height to animate to (you can't animate to auto) this wrapper needs to have a height larger than what your largest sub-menu will have.

In my jsfiddle, I set up the CSS like this:

.nav-sub {
    height:auto;
    background-color:#eee;

}

.nav-sub-holder {
       -webkit-transition:  height 2s ease;  
    -moz-transition: height 2s ease;  
    -o-transition: height 2s ease;    
    transition: height 2s ease;  
    overflow:hidden;    
height:100px;

}


.closed {
    height:0px;
    overflow:hidden;

}

Upvotes: 0

Nick Coad
Nick Coad

Reputation: 3694

There are a few problems with the logic of your code, so I've made some modifications.

$(function navCollapse() {

    var slidedownToggle = $('#global-nav .slidedown-toggle');

    slidedownToggle.click(function () {
        // Get the container item
        var $slidedown = $(this).parents('.slidedown');

        // Get the ul that needs to slide up/down
        var $subnav = $(this).siblings('.nav-sub');

        // Calculate the height required (in px) to show all LIs
        var totalHeight = 0;
        $subnav.find('li').each(function() {
            totalHeight += $(this).height();
        });

        // Set the appropriate height
        if ($slidedown.hasClass('open')) {
            $subnav.css({height: '0px'});
        } else {
            $subnav.css({height: totalHeight + 'px'});
        }
        $slidedown.toggleClass('open');

    });

});

Then in your CSS make sure you apply the transition to your .nav-sub:

-webkit-transition: height 0.2s linear;
-moz-transition: height 0.2s linear;
-ms-transition: height 0.2s linear;
-o-transition: height 0.2s linear;
transition: height 0.2s linear;

Working example:

http://jsbin.com/INIwuTA/11/

Upvotes: 3

Related Questions