1

I'm experimenting with a design pattern using .expands to toggle .hidden child classes for .expanded auto-sized flex box elements.

Something like:

const expandClick = e => {
  e.currentTarget.querySelectorAll('.expanded').forEach(child => {
    child.classList.toggle('hidden')
  })
}

document.querySelectorAll('.expands').forEach(expandable => {
  expandable.addEventListener('click', expandClick)
})

https://jsfiddle.net/vpc8khq8/

When my inner content loses the display: none attribute, I would like the height to ease out with a slight bounce, but I'm not quite sure how to pull that off with a vanilla CSS transition or a pinch of JS.

I came across this post: How can I transition height: 0; to height: auto; using CSS?

But many of the answers seem more like hacks with odd side effects and excess js / css than simple, lightweight solutions.

This does the trick with jQuery: https://jsfiddle.net/cm7a9jr7/

const expandClick = e => {
  $(e.currentTarget).children('.expanded').each(function() {
    $(this).slideToggle('slow', 'swing', function() {
      $(this).toggleClass('hidden')
    })
  })
}

$(() => $('.expands').on('click', expandClick))

But, I'd like to use something leaner. Are the any recommended libraries or simple ways to pull this off in CSS?

AmigaAbattoir
  • 632
  • 8
  • 21
  • 1
    Possible duplicate of [How can I transition height: 0; to height: auto; using CSS?](https://stackoverflow.com/questions/3508605/how-can-i-transition-height-0-to-height-auto-using-css) – VilleKoo Dec 21 '17 at 08:31
  • @VilleKoo I was hoping maybe some libraries popped up in the 7yrs since that post. The max-height accepted answer has some odd side effects (eg, weird delays.) The other answers seem to have some weird effects as well. The comment thread on that post reads `All these answers are not quite "right"` –  Dec 21 '17 at 08:33
  • 2
    animate.css might be the one you're looking for. –  Dec 21 '17 at 09:20
  • @Highdef I might be applying this incorrectly, but this is what I'm looking at with animate.css -- https://jsfiddle.net/rgLf0mhv/ –  Dec 21 '17 at 22:56
  • https://jsfiddle.net/zve449jo/ I was referring to more something like this. And the slideInDown in jquery was overwriting that effect. You can view the rest of the effects : https://daneden.github.io/animate.css/ –  Dec 21 '17 at 23:28
  • @Highdef On first expansion, I don't see any animation. But the subsequent animations would do it, if I didn't see a big empty red block before the content appears. Ideally, the bottom of the red containe wraps around the bottom of the inner content. jQuery does the trick, but I'd rather not go full jQuery-mode. –  Dec 21 '17 at 23:30
  • Here's something I cooked up https://jsfiddle.net/h040nupa/ without the animate.css. Hope, it helps. The only downfall is the height that has to be hardcoded at the end of the animation "300px" –  Dec 22 '17 at 00:05

1 Answers1

0

I've updated your fiddle https://jsfiddle.net/vpc8khq8/2/

Instead of using display none you can get a transition effect by setting max-height to 0 on the hidden section then change the max-height to a fixed height (greater than the section will ever be) to reveal. This also requires you to set overflow hidden on the parent element:

.expands{overflow: hidden;}

section.hidden { 
 max-height: 0;  
 background: red;
}

section{
  transition: 1s cubic-bezier(0.35, 1.17, 0.39, -0.61); 
  max-height: 400px;  
  background: blue;
}

I've created a semi-decent cubic-bezier to get the bounce effect, though with a bit of refinement you could probably get something better.

If you open chrome devtools and click on the transition icon you can select from a number of presets and also create your own by moving the curve points around. Devtools will show you a preview of the transition and you can test it out without reloading. Then just copy that cubic-bezier code back to your CSS.

enter image description here

To take it a step further you could achieve all of this without any JS, using hidden checkboxes and some CSS trickery along the lines of this example: https://codepen.io/mrosati84/pen/AgDry

Pixelomo
  • 6,373
  • 4
  • 47
  • 57
  • 1
    Wow, very nice. I'm still semi-opposed to the max-height attribute (what if the content ranges in height from 60px to 2560px), but I suppose it's necessary. Experimenting with Velocity.js brought similar effects to jQuery (less overhead?) but it's still not as elegant as I'd like. –  Dec 23 '17 at 21:39
  • You could use js to find the tallest content and set max-height based on that. Velocity is faster than jquery at animation but css is faster again which is why I’d always use max-height – Pixelomo Dec 24 '17 at 23:55