0

I have noticed this 'issue' lately when trying some stuff.

Say I want to create a drop-down menu or an accordion.

This is my HTML:

<div class="wrapper" onclick="toggle()">
  I want to be animated!
  <div class="content">
    Was I revealed in a timely fashion?
  </div>
</div>

Stylesheets:

.wrapper {
  background: red;
  color: white;
  height: auto;
  padding: 12px;
  transition: 2s height;
}

.content {
  display: none;
}

.content.visible {
  display: block;
}

JavaScript:

function toggle () {
  var content = document.getElementsByClassName('content')[0];

  var test = content.classList.contains('visible');

  test ? content.classList.remove('visible') :
  content.classList.add('visible');
}

I am trying to achieve a nice, smooth animation when we toggle the state of the content. Obviously this does not work. Anyone can explain to me why it does not work and how to fix it? Many thanks.

Link to the JSFiddle.

lmenus
  • 604
  • 9
  • 27
  • Animating to an auto calculated height is one of those things that is much harder than it should be. Take a look at this SO post http://stackoverflow.com/questions/3508605/how-can-i-transition-height-0-to-height-auto-using-css – mcgraphix Dec 04 '15 at 22:51
  • you need to switch from 2 values and a transition : example http://jsfiddle.net/u9q42yqu/8/ visible/hidden - none/block are 2 states and no transition can be done. it is either seen or not :) – G-Cyrillus Dec 04 '15 at 22:51
  • @GCyrillus: Thank you! However, what if I don't know the height of the content inside? As is often the case .. plus when we have to account for responsive design. – lmenus Dec 04 '15 at 22:53
  • you may use javascript to retrieve height of element in order to set a max-height to each sub-division within a loop or set a bigger value to max-height for a in-between solution :) – G-Cyrillus Dec 04 '15 at 22:55

1 Answers1

1

First things first, some CSS properties CANNOT be transitioned, display is one of them, additionally only discrete values can be transitioned, so height: auto cannot as well.

In your case the problem is with height: auto, while there are a few hacks for doing this, if you are just showing and hiding stuff, why not add, and use jQuery's toggle instead?

$(".content").toggle("slow");

jsFiddle

--EDIT (without jQuery)--

Because it's the auto that is giving us problems, we can use javascript to replace auto with a value in pixels and then use the css transition normally, if your content doesn't have a scroll, we can easily take that value from the scrollHeight property:

function toggle () {
  var content = document.getElementsByClassName('content')[0];

  var test = content.classList.contains('visible');
  console.log(test);

  if (test) {
    content.classList.remove('visible')
    content.style.height = "0px";
  } else {
    content.classList.add('visible');
    content.style.height = content.scrollHeight + "px";
  } 
}

Css

.wrapper {
  background: red;
  color: white;
  height: auto;
  padding: 12px;
  transition: 2s height;
}

.content {
  height: 0px;
  display: block;
  transition: 2s height;
  overflow: hidden;
} /* totally removed .content.visible */

jsFiddle

Community
  • 1
  • 1
Eduardo Wada
  • 2,606
  • 19
  • 31