Jump to content
GreenSock

Roscoeh

Animating height auto

Recommended Posts

Hi,

 

I have an accordion and am animating the the height for a show reveal - the issue is the height which i need to set to auto as the information is different lengths.

 

 

TweenLite.to($content, 1, {css:{height: '0px'}});

$(this).next($content).addClass('active');

    TweenLite.to( $(this).next($content) , 1, {css:{height: "auto"}});

    event.stopPropagation();

 

Can this be done or is there a workaround?

 

Thanks.

Link to comment
Share on other sites

There are a few approaches to this.

Some require checking the natural height of the element and recording that value by placing a property on the actual DOM element or storing the value in an attribute as shown here:

 

http://codepen.io/aPinix/pen/CubGg?editors=001

 

The solution I prefer is when expanding the content from its closed to open state do this

 

- temporarily set the height to "auto"

- immediately start a tween that animates from height:0

 

$(".expander").click(function(){
  var $this = $(this),
      $content = $this.find(".content");
  if(!$this.hasClass("closed")){
    TweenLite.to($content, 0.2, {height:0})
    $this.addClass("closed")
  }else{
    //to open
    // - temporarilty set height:auto
    // - tween from height:0
    TweenLite.set($content, {height:"auto"})
    TweenLite.from($content, 0.2, {height:0})
    $this.removeClass("closed");
  }
})

http://codepen.io/GreenSock/pen/Bzhji?editors=001

  • Like 7
Link to comment
Share on other sites

  • 1 month later...

@Carl
- That approach is clever, but unfortunately it doesn't work with the css propery vmin.

Link to comment
Share on other sites

Hi olsonpm  :)

 

Carl solution works perfectly with Css3 vmin ;

pls check this out :

 

See the Pen NPqVMb by MAW (@MAW) on CodePen

  • Like 4
Link to comment
Share on other sites

  • 11 months later...

Hi Guys,

 

I know this post is old, but I was trying to do something similar, with animating the height:auto property, but I can't seem to get it to work. Here is my codePen 

See the Pen GpaMBa by celli (@celli) on CodePen

... You can see the commented out line animates the div to 600 pixels perfectly, but I want to be able to animate the div to a certain number of pixels depending on the image height that is loaded. Would this approach work for this ?

Link to comment
Share on other sites

Diaco! Awesome, it was just the placement of the auto height setting that I needed in the timeline, thanks!!

Link to comment
Share on other sites

Hey Diaco, One thing I noticed is that if I try and put another tween above the first tween in the timeline, it doesn't seem to work for some reason. I forked your CodePen and just added .to(".box", .75, {opacity:.5}) to the timeline, but anything I put there above the first tween seems to break the code -- why would that be ?

 

See the Pen vNwpbd by celli (@celli) on CodePen

Link to comment
Share on other sites

pls try this :

.from(".workLarge",1,{height:0,immediateRender:false})

See the Pen RWmjJa by MAW (@MAW) on CodePen

  • Like 1
Link to comment
Share on other sites

yes, awesome. that works! Can you explain, why I would need to do that, or in which special instances this is the way to work my tweens ?

Link to comment
Share on other sites

Great work, Diaco. Yes, setting immediateRender to false on that tween is necessary IF you add a tween with a duration at the beginning.

 

Once we understand immediateRender with from() tweens its important to note that although set()s do not have a duration, they only render when they are scheduled inside a timeline.

 

.set(".hidden[data-id="+$(this).attr("data-id")+"]",{display:"block"})
.set(".workLarge", {height:'auto'})
.from(".workLarge", 1, {height:0})

The code above works because the sets have no duration and everything is sitting in the timeline at a time of 0. 

Since the start time is 0, they all render at a time of 0 at practically the same time.

 

When the sets() are the first thing in the timeline, its like giving them immediateRender:true.

 

So the code above does this

 

at time 0: set content to display:block

at time 0: set workflow height:auto

at time 0: set starting height of workflow to 0 and start tweening the height of workflow to whatever auto gives us in pixels

 

BUT if you add a tween at the beginning of the timeline

 

.to(".box", .75, {opacity:.5})
.set(".hidden[data-id="+$(this).attr("data-id")+"]",{display:"block"})
.set(".workLarge", {height:'auto'})
.from(".workLarge", 1, {height:0})

 those sets now are not scheduled to run until a time of 0.75. Unfortunately, that from() tween tries to render immediately BEFORE the sets happen which means there is no height to tween to. The order of execution in the code above is

 

  • at time 0: create tween that fades opacity to 0.5
  • at time 0: the from() tween sets the starting value of workflow's height to 0 (because immediateRender is true) and its contents haven't yet been given display:block
  • at time 0.75: set display of that thing to block
  • at time 0.75: set height of workLarge to auto
  • at time 0.75: start the from() tween animating the height of workLarge from 0 to 0

 

So when we set immediateRender:false on the from() tween like Diaco suggested it just makes sure that the sets() happen first.

 

 

 

Hopefully this clears things up. 

BTW Great demo, Celli!

  • Like 6
Link to comment
Share on other sites

so , this works too :

   .fromTo(".box", 0.7,{opacity:1},{opacity:.5})
   .set(".hidden[data-id="+$(this).attr("data-id")+"]",{display:"block"},0) // set position parametr to 0
   .set(".workLarge",{height:'auto'},0) // set position parametr to 0
   .from(".workLarge",1,{height:0})
   .fromTo(".hidden[data-id="+$(this).attr('data-id')+"]",1,{opacity:0},{opacity:1});

thanks Carl for detailed explanation :)

  • Like 4
Link to comment
Share on other sites

Great explanation of using set() in a timeline with from() tween Carl.. like butter on bread :)

  • Like 1
Link to comment
Share on other sites

makes sense. thanks for everything guys!

Link to comment
Share on other sites

Hi again guys... One more thing I was thinking of and trying to achieve is--what if the height of the div is not coming from zero, because there is already an image there--and the height needs to go from 150px to say, 600px ? Is there also a way to write that code so that if it is >0 then use the _current.height that it currently is at ?

Link to comment
Share on other sites

I would think that I can do this, and it would work:

.from(".workLarge", 1, {height:$(".workLarge").outerHeight(), immediateRender:false, ease:Expo.easeInOut})

it doesn't seem to really work though: 

See the Pen vNwpbd by celli (@celli) on CodePen

Link to comment
Share on other sites

pls try this :

$(".box").click(function(event) {  
  var H = $(".workLarge").outerHeight();
  TweenLite.set(correctImage, {clearProps:"all"})
  //...
  .from(".workLarge", 1, {height:H,immediateRender:false})
  //...
});
  • Like 2
Link to comment
Share on other sites

thats great Diaco. Works perfectly :) I did notice that I need to put that before I set the clearProps, and I wasn't sure exactly why... but it works very well!

Link to comment
Share on other sites

  • 1 year later...

Thanks for the helpful codepen!

 

By the way, the images used in the codepen

See the Pen vNwpbd by celli (@celli) on CodePen

 are no longer available, so it is not clear at first things are working

 

 

  • Like 1
Link to comment
Share on other sites

hi metaltab,

 

thanks for the info. i forked celli's demo and added 2 images from lorempixel

 

incase it helps others:

 

See the Pen yXWmPO by GreenSock (@GreenSock) on CodePen

 

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×