jQuery slideDown with set height and overflow

21,943

Solution 1

Try this it is very simple and easy without creating any clone.

$(function(){
    $(".button").click(function(){
        var $text = $(".text");
        var contentHeight = $text
                            .addClass('heightAuto').height();
        $text.removeClass('heightAuto').animate({ 
            height: (contentHeight == $text.height() ? 100 : contentHeight)
        }, 500);

    });
});

Added a new class

.heightAuto{
    height:auto;
}

Demo

Solution 2

I like Shankar's solution but the functionality breaks down after the first two clicks.. This is because the auto class gets overwritten by the inline height style. So instead I altered the height attribute only.

Here's my go at it:

$(".button").click(function(){
    $box = $(".text");
    minimumHeight = 100;

    // get current height
    currentHeight = $box.height();

    // get height with auto applied
    autoHeight = $box.css('height', 'auto').height();

    // reset height and revert to original if current and auto are equal
    $box.css('height', currentHeight).animate({
        height: (currentHeight == autoHeight ? minimumHeight : autoHeight)
    })
});

One flaw is that if you add padding to the box you get some ugly jumping. Open to any solutions to fix that.

Here's a demo

Improvements and suggestions are very welcome

Solution 3

Clean but expensive option: Use animate directly instead of slideDown(). Determine the height you want to animate to by creating a clone and setting the height to auto.

$('.button').click(function() {
   var $div = $('div.text');
   $div.animate({height: determineActualHeight($div)});
});

// if you can determine the div's height without this, it would be faster
// what makes this expensive is inserting and removing an element from the dom
// of course, you aren't doing this a thousand times a second, so it's probably no biggie
function determineActualHeight($div) {
   var $clone = $div.clone().hide().css('height', 'auto').appendTo($div.parent()),
       height = $clone.height();
   $clone.remove();
   return height;
}

A little uglier but less expensive option: just set the height to auto, hide the element, then use slideDown() to render it:

$('.button').click(function() {
   $('div.text').hide().css('height', 'auto').slideDown();
}

Solution 4

I just totally misread your question.

Unfortunately, you can't really set to auto height. But you can animate to a set height, using .animate();

.animate({height:'200px'};

slideUp()' and .slideDown(); set the divs to display: none and display: block So you're right, that wouldn't work for what you're trying to do.

EDIT

I just saw Kato's post. That's probably the best option for you.

Solution 5

Shankar and Erik's solutions are on the right track. Erik fixed Shankar's problem of only working twice. Now I'm going to fix Erik's problem of having padding:

$(function(){
    $(".arrow-details").click(function(e){
        var id = "#other-" + e.target.id;
        var $box = $(id);
        minimumHeight = 350;
        currentHeight = $box.outerHeight();
        autoHeight = $box.css('height', 'auto').outerHeight();
        $box.css('height', currentHeight).animate({
            height: (currentHeight == autoHeight ? minimumHeight : autoHeight)
        })
    });
})

Basically, I took Erik's jsfiddle and changed innerHeight to outerHeight.

Demo

I also had several divs on my page where the height can change, so instead of hard coding which div gets changed, the impacted div is now determined by the ID of the button/image/div the user clicks on.

Share:
21,943
stergosz
Author by

stergosz

Joomla & WordPress developer based in Greece Developing Joomla extensions on tassos.gr Developing WordPress plugins on fireplugins.com

Updated on December 05, 2020

Comments

  • stergosz
    stergosz over 3 years

    I have the following HTML code

    <div class="text">bla bla bla bla</div>
    <div class="button">Show</div>
    

    And the CSS

    .text{
      height:100px;
      overflow:hidden;
    }
    

    Assume .text div has way more text and what I do is hide the amount of text below 100px.

    How can I slideDown() the div so I can view the text when I click the button?

    Using $(".button").slideDown(); doesn't work because I need to remove the height and then slideDown() but this will not work either.

  • Gordnfreeman
    Gordnfreeman over 12 years
    beat me to it haha i made a fiddle for the second option :O (yours was a bit cleaner however) jsfiddle.net/GordnFreeman/thJwU/9 :)
  • Kato
    Kato over 12 years
    And that truly is the conundrum of SO is it not? Answer it thoroughly or answer it fast? Thus, I always try to upvote ALL the useful answers, and not just the first one, particularly if each contains some unique helpful detail. :) If you did the work, you should post your answer; I'm sure it will help someone.
  • Kato
    Kato over 12 years
    You're on the right track, your first answer was also not bad. You just need the height: auto in the css to get things rolling :)
  • Jeremy Miller
    Jeremy Miller over 12 years
    Ah, I didn't realize the height: auto worked with .slideDown(); - doesn't it default to display: none? Also, I wasn't aware you could do .animate(); to height: auto Ha, I'm certainly no jQuery master, so I've still got a ways to go.
  • Kato
    Kato over 12 years
    Interesting; I thought the 'blip' that would occur when you set height: auto would be much more noticeable. Is this because the CSS doesn't get rendered until the function returns (i.e. quasi-threading)?
  • ShankarSangoli
    ShankarSangoli over 12 years
    It happens within fraction of micro seconds so.
  • stergosz
    stergosz over 12 years
    well i dont want to hide it... simply slideDown it or animate it
  • Kato
    Kato over 12 years
    I'm thinking it doesn't even happen. I've noticed before that I have to setTimeout() when I make css changes then try to utilize them right away. I suspect the CSS change doesn't get applied until the js method exits.
  • Kato
    Kato over 12 years
    well then you want the first approach, or +ShankarSangoli's. FYI - the second option doesn't hide it, just simply makes it expand from zero instead of the current height.
  • Jordan Miner
    Jordan Miner over 11 years
    CSS doesn't get rendered until JavaScript finishes. And the size of elements isn't calculated until the size is needed or the page is rendered. When the height: auto is first added, the browser doesn't render it or calculate the new size. Then it calculates the size when height() is called. Since the height: auto is removed before the end of the function, the browser never gets a chance to render it that way.