Expandable Div with transition in CSS

advertisements

I have a div at the top of my page, containing some header text, which, upon mouseenter, should expand (in height), to reveal some smaller text. Then, upon mouseleave, it should then retract. This is harder than it sounds...

The solution must:

  1. Go from a height to fit just the header, to a height to fit all the text.
  2. Transition from one to the other.
  3. Try to use pure CSS.
  4. Have the expanding animation pause if the mouse leaves, and visa versa (default in CSS, but not in jQuery).

I have tried:

  1. Using :hover in my stylesheet, to change from a set pixel value, to auto, as seen in this question (but in mine it is pure CSS). This did not transition.
  2. Using a set height upon expansion, which does not work on different viewport sizes.
  3. Using max-height, and expanding it to something larger than the actual expanded div would get, as seen in this question. This meant that the transitions don't work properly, and look different on different devices.
  4. Using jQuery .animate(), using the pixel value of auto, to then create a transition, as seen in this question, but the animation has to finish before starting the next one, meaning that a series of animations could continue for a long time after the user's mouse if far away from the div.

See all four above examples here.

As said, pure CSS would be ideal, but if not possible, I would be fine with JavaScript (and I prefer jQuery).

Thanks! :)


I am not aware of any pure CSS solution for this – transitioning values to auto is something the specification did not include; I think that was even an explicit decision based on that there might be implementation problems.

But for a “simple” jQuery solution, I’d just wrap the paragraph content inside an additional span, set the initial paragraph height to 0 and overflow:hidden, leave the transition for the height in place – and then let jQuery only do one thing, read the height of the span element, set that height for the paragraph, and then set it to 0 again to fade the text out again.

.details {
  height: 0;
  margin: 0;
  overflow: hidden;
  transition: height 1s;
}

$("div").mouseenter(function() {
  $(this).find('p').css('height', $(this).find('span').height());
})

$("div").mouseleave(function() {
  $(this).find('p').css('height', 0);
})

That way, CSS still does the “heavy lifting” of handling the height change via transition (that might should be optimized in browsers), and jQuery/JavaScript is only used to give it the little “nudge” it needs to know what to do. (Pretty sure jQuery is doing the same thing internally as well nowadays with animate(), if the browser supports it – added benefit there would be that jQuery takes care of a fallback implementation, should a really old browser not support transition; in my solution the height would just change instantly, without any transition.)

https://jsfiddle.net/ypwu9n0g/7/

Please notice that in that example, the method is the same for all four items, and I did not bother to change the text content ;-)