Reputation: 569
I want the height to expand smoothly, but 95% of the time, the transition doesn't happen. Is this because the classList.toggle creates a new class string, and therefore the transition is lost? Either way, how do I resolve this? I must use vanilla JS for this.
document.querySelectorAll('.toggleMe').forEach(function (query) {
query.onclick = function (e) {
e.target.classList.toggle('open');
}
});
.toggleMe {
background: #e3e3e3;
max-height: 1.3rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
transition: all ease 2s;
-moz-transition: all ease 2s; /* Firefox 4 */
-webkit-transition: all ease 2s; /* Safari and Chrome */
-o-transition: all ease 2s; /* Opera */
-ms-transition: all ease 2s; /* Explorer 10 */
}
.toggleMe.open {
max-height: 999px;
white-space: normal;
}
<div class="toggleMe">I am a really long sentence that wants to stay hidden on load, but when clicked will expand for all to see. But 95% of the time, the transition doesn't happen. Is this because the classList.toggle creates a new class string, and therefore the transition is lost?</div>
Upvotes: 2
Views: 736
Reputation: 9437
Think of the max-height
setting as a window/viewport kind of thing which opens and closes vertically in an animated way.
Meanwhile, the white-space
setting causes the paragraph to increase or decrease in height instantly, without animation.
When the paragraph instantly increases in height, you only see the animation if the window starts out in a fully closed position, because as the window begins to open, it reveals the paragraph as it goes.
When you collapse, the paragraph collapses instantly, but it takes a full 2 seconds for the max-height
window to close. It isn't obvious because all of that time is spent traversing almost 999px
of imaginary real estate.
So, you must wait the full 2 seconds for that window to close, in order to see an expand animation the next time. Otherwise, if you don't wait, the window is still partly open, and it begins to open again without first settling to its minimum height. Thus, it fails to re-create the animation.
I assume that the reason it seems to intermittently fail, is that during your testing you were waiting varying amounts of time between expand, collapse, and re-expand.
I hope that makes sense. It's definitely a bit tricky to create an expand/collapse effect on text which has unpredictable height. If you reduce the max-height: 999px
setting, it could minimize the problem. But then it might cut off bigger paragraphs :/
Upvotes: 3
Reputation: 643
These below are the problems you are facing in your code.
If you click the element before the animation ends in 2s, you will not be able to see next animation correctly.
When you take off .open from the element class by toggling, white-space: nowrap instantly comes into effect, which causes an immediate height change without animation.
It is because the content does not exit to fill the decreasing height by animation.
If you really want the text ellipsis effect, you can show it by pseudo element like ::after.
.toggleMe {
background: #e3e3e3;
overflow: hidden;
text-overflow: ellipsis;
line-height: 18px;
position: relative;
max-height: 18px;
padding-right: 2px;
width: 100%;
cursor: pointer;
transition: all ease 0.2s;
-moz-transition: all ease 0.2s;
/* Firefox 4 */
-webkit-transition: all ease 0.2s;
/* Safari and Chrome */
-o-transition: all ease 0.2s;
/* Opera */
-ms-transition: all ease 0.2s;
/* Explorer 10 */
}
.toggleMe.open {
max-height: 999px;
}
.toggleMe::after {
content: '...';
position: absolute;
right: 4px;
top: 0;
}
.toggleMe.open::after {
display: none;
}
Upvotes: 2
Reputation: 22386
you can use arrow function to ignore event target
document
.querySelectorAll('.toggleMe')
.forEach( el => el.onclick = _ => el.classList.toggle('open') )
Upvotes: 1
Reputation: 21
Try use e.currentTarget
instead e.target
document.querySelectorAll('.toggleMe').forEach(function (query) {
query.onclick = function (e) {
e.currentTarget.classList.toggle('open');
}
});
.toggleMe {
background: #e3e3e3;
max-height: 1.3rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
transition: all ease 2s;
-moz-transition: all ease 2s; /* Firefox 4 */
-webkit-transition: all ease 2s; /* Safari and Chrome */
-o-transition: all ease 2s; /* Opera */
-ms-transition: all ease 2s; /* Explorer 10 */
}
.toggleMe.open {
max-height: 999px;
white-space: normal;
}
<div class="toggleMe">I am a really long sentence that wants to stay hidden on load, but when clicked will expand for all to see. But 95% of the time, the transition doesn't happen. Is this because the classList.toggle creates a new class string, and therefore the transition is lost?</div>
Upvotes: 1