Search code examples
jqueryjquery-effects

jquery slideDown - sliding down more than required and then reversing


Here is my code

$.get("insert-note.exec.php", {mess: messIn}, function(ajaxContent) {
   if(ajaxContent != 0) {    
      $('#message-text').val('');  
      $('#insert-flag').after(ajaxContent);  
      $('#insert-flag').next('.message-bubble').slideDown('slow');
   }
});

CSS Part

#message-text {
 padding:4px;
 outline:none;
 color:#FFF;
 border:3px solid #101010;
 background-color:#FFF;
 border-radius:6px;
 -moz-border-radius:6px;
}    

.message-bubble {
 width:92%;
 padding:1.50%;
 margin-bottom:2%;
 letter-spacing:1px;
 border-radius:8px;
 overflow:hidden;
 cursor:pointer;
 -moz-border-radius:8px;
 background-color:#FFF;
 -moz-box-shadow: 1px 1px 1px #FFF;
 -webkit-box-shadow: 1px 1px 1px #FFF;
 box-shadow: 1px 1px 1px #FFF;
}

#insert-flag {
  width:0;
  height:0;
}

In short, I am trying to fetch data (ajax) from server which is returned as a div and I am trying to slide the div into the current interface.

Problem: It all works as expected except that the new div slides a little extra lower and then recovers to the appropriate size.

For example: For a 3-line div, the effect results in an initial slideDown of, let say, 5-lines and then akin to a effect of slideUp adjusts itself to the appropriate 3-lines.

How can I handle this?

(Note: A similar effect can be seen at Loopt which works properly when new content is pushed)


Solution

  • This is a fairly well known bug with jQuery's slide methods. It occurs when the div being slided does not have a defined height. Perhaps using .delay() as suggested in a comment will work. But another, possibly more robust solution, is that you first make the div that will get filled with the response data have a style like position:absolute; visibility:hidden. This will allow you to get the height of the div without the user initially seeing the content.

    So something like:

    <style>
    .message-bubble {position:absolute; visibility:hidden}
    </style>
    
    <script>
    $.get("insert-note.exec.php", {mess: messIn}, function(ajaxContent) {
       if(ajaxContent != 0) {    
          $('#message-text').val('');  
          $('#insert-flag').after(ajaxContent);
          var newContent = $('#insert-flag').next('.message-bubble');
    
         //set an inline style attribute to the correct height, and prepare the div for slideDown()
          newContent.css({
               height:newContent.height() + 'px',
               display:'none',
               visibility:'visible'
               position:'relative',
          });
          newContent.slideDown('slow');
       }
    });
    </script>