Jessica
Jessica

Reputation: 9830

Height doesn't transition all the way

I'm trying to show an element for a second, then hide it. When a button gets clicked on, a class gets added, which has the opacity and max-height values. When that's finished animating, the class gets removed, and the element stays on screen for a second, due to the transition delay.

The problem is, when the buttons gets selected, the element doesn't go to its full height, unless:

What am I doing wrong, and how can I fix it? (I need to have max-height, and not height.)

JSFiddle

var btn = document.getElementById('btn');
var elem = document.getElementById('elem');

btn.addEventListener('click', function() {
  elem.classList.add('show');
});

elem.addEventListener("transitionend", function() {
  elem.classList.remove('show');
}, false);
#reference {
  height: 100px;
  background-color: lightblue;
  font-size: 20px;
  text-align: center;
}
#elem {
  background-color: orange;
  font-size: 20px;
  text-align: center;
  max-height: 0px;
  opacity: 0;
  transition: max-height 400ms ease, opacity 100ms ease;
  transition-delay: 1000ms;
}
#elem.show {
  opacity: 1;
  max-height: 100px;
  transition-delay: 0ms;
}
#inner-content {
  padding: 20px;
}
<div id="reference">Height of 100px</div>
<button id="btn">Press Me</button>
<div id="elem">Should get a height of 100px
  <div id="inner-content">Some Text</div>
</div>

Upvotes: 1

Views: 116

Answers (3)

Chase
Chase

Reputation: 2304

To solve both the multiple clicks and the transition height problem you need to do a bit of a workaround. transitionend actually fires four times. Twice for max height and twice for opacity. You need to track when the button is clicked and reset it after the fourth transition. The reason the height is not going to the full 100px is because you're removing the show class right after the opacity transition and not the first max-height. You can see this if you put a console.log(e.propertyName) in your transitionend event listener. This code works, but it is a bit ugly. I'm sure if you thought about it a bit there would be a better way to do it.

var btn = document.getElementById('btn');
var elem = document.getElementById('elem');
var hasClick = false;
var maxCount = 1;
btn.addEventListener('click', function() {
  if(!hasClick) {
      elem.classList.add('show');
      hasClick = true;
    }
  
});

elem.addEventListener("transitionend", function(e) {
  console.log(e.propertyName);
  if(e.propertyName=="max-height"){
    elem.classList.remove('show');
    
    if(maxCount>1){
        hasClick = false;
        maxCount = 0;
     }
    maxCount++
    }
}, false);
#reference {
  height: 100px;
  background-color: lightblue;
  font-size: 20px;
  text-align: center;
}
#elem {
  background-color: orange;
  font-size: 20px;
  text-align: center;
  max-height: 0px;
  opacity: 0;
  transition: max-height 400ms ease, opacity 100ms ease;
  transition-delay: 1000ms;
}
#elem.show {
  opacity: 1;
  max-height: 100px;
  transition-delay: 0ms;
}
#inner-content {
  padding: 20px;
}
<div id="reference">Height of 100px</div>
<button id="btn">Press Me</button>
<div id="elem">Should get a height of 100px
  <div id="inner-content">Some Text</div>
</div>

Upvotes: 1

Asons
Asons

Reputation: 87191

2 things;

  • your transitionend fires after 100ms, the opacity, hence the max-height has still 300ms left, which of course gets cancelled when you switch the class

  • the inner-content is not big enough to occupy 100px height

So if you update your transitionend function like this, it will work and wait for max-height to fire

elem.addEventListener("transitionend", function(e) {
    if (e.propertyName != 'opacity') {
      elem.classList.remove('show');
    }
}, false);

Stack snippet

var btn = document.getElementById('btn');
var elem = document.getElementById('elem');

btn.addEventListener('click', function() {
    elem.classList.add('show');
});

elem.addEventListener("transitionend", function(e) {
    if (e.propertyName != 'opacity') {
      elem.classList.remove('show');
    }
}, false);
#reference {
    height: 100px;
    background-color: lightblue;
    font-size: 20px;
    text-align: center;
}
#elem {
    background-color: orange;
    font-size: 20px;
    text-align: center;
    max-height: 0px;
    opacity: 0;
    transition: max-height 400ms ease, opacity 100ms ease;
    transition-delay: 1000ms;
}

#elem.show {
    opacity: 1;
    max-height: 100px;
    transition-delay: 0ms;
}

#inner-content {
    padding: 40px;
}
<div id="reference">Height of 100px</div>
<button id="btn">Press Me</button>
<div id="elem">Should get a height of 100px
    <div id="inner-content">Some Text</div>
</div>

Upvotes: 2

Vcasso
Vcasso

Reputation: 1348

Your transition runs too fast for the height to get completed. Try changing your transiton to----- transition: max-height 2s ease, opacity 1s ease;

Here is the screen video: https://www.screencast.com/t/Z1OFiQabl

Upvotes: 0

Related Questions