3

[My question differs from the suggested duplicate because of the presence of padding in my animated div]

Trying to get a div to expand, without having fixed heights and with some padding. My css is below and I toggle .closed in and out using jquery.

.slide {
  padding: 10%;
  background-color: gold;
  overflow-y: hidden;
  transition: height 2s;
  transition: max-height 2s;
  height: auto;
  max-height: 1000px;
}

.closed {
  height: 0;
  max-height: 0;
}

The issue is that with the padding you can't hide the text to start with, and without a fixed height you don't get a transitioned css change. Can anyone help - hope I don't need to do more with javascript?

Update I've now got to:

.slide {
  padding: 10%;
  background-color: gold;
  overflow-y: hidden;
  transition: max-height 2s ease;
  max-height: 500px;
}

.closed {
  max-height: 0;
  padding: 0;
  transition: all 2s ease;
}

See plnkr. The problem now is the padding on closing. In the case above it transitions out, and if i limit the transition in .closed to max-height then there is a jarring effect as it collapses just as the animation starts.

Simon H
  • 20,332
  • 14
  • 71
  • 128
  • 1
    You can't transition to `height:auto` in CSS..even JQuery can't do that natively...although there are plug-ins to add that functionality. You could try transitioning `max-height` instead. – Paulie_D Jun 12 '15 at 18:09
  • 1
    max height will work as long as you wrap the content in something. That's the only thing you are missing: http://plnkr.co/edit/3caEykW27d7pgHOfT6Fp?p=preview. It does however have an unsightly delay for close. – Joseph Marikle Jun 12 '15 at 18:20
  • 1
    @Paulie_D definitely not a duplicate, this question is about padding. – Christophe Nov 22 '15 at 06:37

2 Answers2

5

Hello I imagine that you have this fixed now as you posted a long time ago, but I just came across the same situation and made my own solution.

Basically I just created an empty div within the element that you are showing/hiding and applied the padding to that.

<ul class="dropdown-menu" role="menu">
    <div class="padding-div">
          <li>menu-item</li>
          <li>another-menu-item</li>
          <li>yet-another-menu-item</li>
     </div>
</ul>


.dropdown-menu {
    display: block;
    position: absolute;
    background: #fff;
    list-style: none;
    overflow: hidden;
    max-height:0;
    transition: max-height 0.7s ease-in;
    right: 0;
    top: 60px;
    width: 125px;
}

.padding-div {
    padding: 20px;

    /* Whatever you need to position everything correctly again eg.*/
    position: relative;
    right: 10px;
    text-align: center;
}
ccchoy
  • 704
  • 7
  • 16
Rob Hughes
  • 876
  • 2
  • 13
  • 32
0

This is partially in the updated answer and also partially in the updated plnkr link, but I overlooked that the plnkr link had updated code that's not in the post, and I instead used another answer's suggestion to use a wrapper div, so here's the alternate, updated answer:

To transition a div whose height comes from its content into a sliding open/closed motion using CSS, you should do the following:

  • Use max-height to collapse the element because transitioning to height: auto doesn't work
  • Use overflow hidden along with the transition so that the content is properly contained while the height changes
  • If you have padding within the element, you'll notice collapsing the height doesn't fully collapse the element - because of this we should also remove padding when closed. Note: the same is also true for margin.
  • Should only collapse padding/margin-top/bottom so that the content doesn't move horizontally on collapse since we're collapsing vertically. Flip this if you want to collapse horizontally via width instead.

1 final note (while a bit dated), if you're already using JQuery, you can use JQuery's slideToggle to accomplish this same functionality. In fact, it's doing almost the exact same CSS changes (shrinking height and vertical margin/padding with overflow hidden) only with JS rather than CSS transitions. You can see this for inspiration/memory if you inspect an element while it's toggle sliding via JQuery.

$(document).ready(function() {
  $(".btn").on("click", function() {
    console.log("click");
    $(".slide").toggleClass("closed");
  });
  
  $(".btn2").on("click", function() {
    $(".slide2").slideToggle(2000);
  });
});
.slide {
  padding: 10%;
  background-color: gold;
  overflow-y: hidden;
  transition: padding-top 2s, padding-bottom 2s, margin-top 2s, margin-bottom 2s, max-height 2s;
  max-height: 1000px;
}

.closed {
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  margin-top: 0;
  margin-bottom: 0;
}

.slide2 {
  padding: 10%;
  background-color: gold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button class="btn">Press Me</button>
<div class="slide closed">
  <div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptas temporibus tempore cumque aut. Culpa voluptatibus laudantium laborum dolor quae. Assumenda, beatae, similique repudiandae adipisci ipsam quisquam veniam quaerat eveniet nobis.</div>
  <div>Laboriosam, ut, rerum, natus consequatur dolores nulla quaerat mollitia reiciendis harum vitae at rem architecto pariatur provident quam velit error numquam incidunt repellat nam temporibus magni ullam minima ducimus magnam.</div>
</div>
<p>Multiple things needed here to make this work:
  <ul>
    <li>For content with variable height (i.e. height: auto), use max-height instead since CSS transitions for height: auto don't work.</li>
    <li>Once the padding is added in, because we're only collapsing the height, the padding remains. On close, should remove the padding as well with padding: 0.</li>
    <li>Notice with padding: 0 now, it collapses entirely but there's a jarring effect where the content moves in/out from the corner. This is because on close, we're removing the vertical <i>and</i> the horizontal padding. The close is only vertical though so we really only need to remove the vertical padding and the horizontal padding can remain so instead use <code>padding-top: 0; padding-bottom: 0;</code></li>
    <li>Finally update transition property to transition the appropriate attributes - padding-top and padding-bottom or all if that works for you.</li>
  </ul>
</p>

<button class="btn2">With JQuery</button>
<div class="slide2" hidden>
  <div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptas temporibus tempore cumque aut. Culpa voluptatibus laudantium laborum dolor quae. Assumenda, beatae, similique repudiandae adipisci ipsam quisquam veniam quaerat eveniet nobis.</div>
  <div>Laboriosam, ut, rerum, natus consequatur dolores nulla quaerat mollitia reiciendis harum vitae at rem architecto pariatur provident quam velit error numquam incidunt repellat nam temporibus magni ullam minima ducimus magnam.</div>
</div>
ccchoy
  • 704
  • 7
  • 16