Edward144
Edward144

Reputation: 487

CSS/Javascript animate height expand and collapse for items with varying height

I am trying to create a menu with various tabs that can be clicked to expand, then clicked again to collapse.

I have successfully used css animations/transitions to achieve this by changing max height. However each of the boxes will hold different amount of content leading to varying heights. Which in turn causes them each to animate at different speeds.

It is not so much a problem for expanding the boxes, but is very noticeable when collapsing them again, as some will appear to do nothing for a period then suddenly close quickly, when others close in a smooth motion.

Example of the CSS, plus some simple jQuery to add and remove the active id:

.options .optionTab > div {
    max-height: 0;
    overflow: hidden;
    transition: max-height 2s ease;
}

.options .optionTab#active > div {
    max-height: 1000px;
    transition: max-height 2s ease;
}

$(".optionTab > h3").click(function() {
    if($(this).closest(".optionTab").attr("id") == "active") {
        $(this).closest(".optionTab").attr("id", "");
    }
    else {
        $(this).closest(".optionTab").attr("id", "active");        
    }
});

JSFiddle

Is there a way using either css or javascript animations to achieve a consistent animation speed amongst varying height items?

Upvotes: 1

Views: 1134

Answers (3)

Basil Abubaker
Basil Abubaker

Reputation: 1651

Accordion

You can use JqueryUI Accordion and modify the interface with a custom css to look exactly the way you want it to look. this will save you time that you can invest in the rest of the project

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>jQuery UI Accordion - Collapse content</title>
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <link rel="stylesheet" href="/resources/demos/style.css">
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <script>
  $( function() {
    $( "#accordion" ).accordion({
      collapsible: true,
      active: false
    });
  } );
  </script>
</head>
<body>
 
<div id="accordion">
  <h3>Section 1</h3>
  <div>
    <p>Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut odio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate.</p>
  </div>
  <h3>Section 2</h3>
  <div>
    <p>Sed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor velit, faucibus interdum tellus libero ac justo. Vivamus non quam. In suscipit faucibus urna. </p>
  </div>
  <h3>Section 3</h3>
  <div>
    <p>Nam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis. Phasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero ac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis lacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui. </p>
    <ul>
      <li>List item one</li>
      <li>List item two</li>
      <li>List item three</li>
    </ul>
  </div>
  <h3>Section 4</h3>
  <div>
    <p>Cras dictum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia mauris vel est. </p><p>Suspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </p>
  </div>
</div>
 
 
</body>
</html>

Upvote if you like it

Upvotes: 2

Shankar Bhattarai
Shankar Bhattarai

Reputation: 1

you can try this

$(".optionTab").each(function() {
  var self = $(this);
  var slideHolder = self.find('>div');
  var heading = self.find("h3");
  var initialHeight = slideHolder.outerHeight();
  slideHolder.css('height',0);
  
  heading.on('click', function(e) {
    e.preventDefault(); //if it is anchor tag 
    slideHolderHeight = $(this).next().outerHeight();
    var checkFlag = (slideHolderHeight > 0) ? true : false;
    console.log(slideHolder);
    
    slideHolder.animate({
     height: checkFlag ? 0 : initialHeight
   },300)
  });
});
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

.options {
  background: #fff;
}

.options .optionTab h3 {
  background: #f3f3f3;
  padding: 1em;
  box-sizing: border-box;
  margin: 0;
  cursor: pointer;
}

.options .optionTab h3:hover {
  background: #ccc;
}

.options .optionTab > div {
  overflow: hidden;
  transition: max-height 2s ease;
}

.options .optionTab > div > div {
  padding: 1em;
  box-sizing: border-box;
}

Upvotes: 0

Lonnie Best
Lonnie Best

Reputation: 11364

I notice that you're using ease in your CSS transition.

Try changing your transition-timing-function to linear. Perhaps changing the timing function will lead to varying heights completing the animation in the same amount of time. Also try ease-out.

Upvotes: 0

Related Questions