jquerycssslidetoggle

Stop padding change during jquery slideToggle


Is there a way to stop the text from moving during a call to jQuery slideToggle?

In the following example, the text moves up while the <div> is being hidden, and moves down while it is becoming visible...

$("a").on("click", function(e) {
  e.preventDefault();
  $("#outer").slideToggle(1000);
});
#outer {
  padding:10px;
  border:1px solid #aaa;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p><a href="#">Show/Hide</a></p>
<div id="outer">Some text<br/>Some text<br/>Some text<br/>Some text<br/>Some text</div>


One solution appears to be to nest the <div> with padding within another <div> and doing the slide on the outer <div>. But it would make my life a little easier if I could make it work without needing to nest them.

$("a").on("click", function(e) {
  e.preventDefault();
  $("#outer").slideToggle(1000);
});
#outer {
  border:1px solid #aaa;
}
#outer > div {
  padding:10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p><a href="#">Show/Hide</a></p>
<div id="outer"><div>Some text<br/>Some text<br/>Some text<br/>Some text<br/>Some text</div></div>


Solution

  • This is because (as per this answer), both height and padding contribute to the overall height of the div, and jQuery knows this so is animating the top and bottom padding towards 0 at the same time as the height. Because the outer div's padding is decreasing you get the effect of its content shifting upwards.

    One way to circumvent this would be to override jQuery's padding shift by putting an !important on the padding property in your CSS. However note that, because the total height of the div is equal to padding + height, this means the outer div will not decrease to a true height of 0, but will only decrease to a minimum of 20px (top + bottom padding) before being removed by jQuery.

    $("a").on("click", function(e) {
      e.preventDefault();
      $("#outer").slideToggle(1000);
    });
    #outer {
      padding:10px!important;
      border:1px solid #aaa;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <p><a href="#">Show/Hide</a></p>
    <div id="outer">Some text<br/>Some text<br/>Some text<br/>Some text<br/>Some text</div>

    Another workaround is to do exactly what you've already found and wrap the content with an inner div that has padding. This way there will be no animated padding on the outer div and the effect will display as intended.