I am trying to implement a 'toggle visibility with sliding motion' functionality like jQuery's slideDown() in plain JS.
I can animate values over time, no problem, but what do I do when the height of the element that should become visible is unknown?
Existing sample solutions always seem to animate the max-height value up to a fixed value, but I need to animate to previously unknown value (height).
(If there's a way to achieve this with css3, I would also be curious!)
I am trying to implement a 'toggle visibility with sliding motion' functionality like jQuery's slideDown() in plain JS.
I can animate values over time, no problem, but what do I do when the height of the element that should become visible is unknown?
Existing sample solutions always seem to animate the max-height value up to a fixed value, but I need to animate to previously unknown value (height).
(If there's a way to achieve this with css3, I would also be curious!)
Share Improve this question asked Mar 20, 2016 at 14:24 HoffHoff 39.8k17 gold badges82 silver badges103 bronze badges 06 Answers
Reset to default 15 +100Set the height of your element to 0, with hidden overflow, and a CSS3 transition to handle the animation:
.container {
height: 0px;
overflow: hidden;
transition: all 1000ms;
}
You can then easily animate the element based on its scrollHeight
:
var container= document.querySelector('.container');
container.style.height= container.scrollHeight + 'px';
Snippet
document.querySelector('button').addEventListener('click', function() {
var container= document.querySelector('.container');
container.style.height= container.scrollHeight + 'px';
});
.container {
font: 24px verdana;
background: #dfd;
height: 0px;
overflow: hidden;
transition: all 1000ms;
}
<button>
Slide Down
</button>
<div class="container">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
Fiddle
you can do test if <input type="button" id="slide" value =" Slide Down "/>
has parent, and if he hasn't parent (= his parent is <body>
), you can do that :
var maxheight = $(window).height();
see https://jsfiddle.net/9xco9t8o/
document.getElementsByTagName('div')[0].onclick = function() {
this.style.height = this.offsetHeight + 'px';
var that = this;
setTimeout(function() { that.style.height = '0'; }, 10);
};
div {
width: 50px;
background-color: yellow;
overflow: hidden;
transition: height 300ms ease;
}
<div>
<p>Let us not talk falsely now</p>
</div>
As I can see the most solutions are based on animation of "height" property which can be laggy due to browser repaint processes (especially on mobile devices). That's why I'd propose to use animation of "transition" and "opacity" properties to simulate the changing of height;
Fiddle: https://jsfiddle.net/av6207fy/3/
This solution will behaves more smoothly because of using "transform" and "opacity" properties animation. You can read more about it here http://www.html5rocks.com/en/tutorials/speed/high-performance-animations/
HTML
<div class="slider">
<div class="slider-header">
Click to toggle
</div>
<div class="slider-body">
"At vero eos et accusamus et iusto odio dignissimos ducimus qui
blanditiis praesentium voluptatum deleniti atque corrupti quos dolores
et quas molestias excepturi sint occaecati cupiditate non provident,
similique sunt in culpa qui officia deserunt mollitia animi, id est
laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita
distinctio. Nam libero tempore, cum soluta nobis est eligendi optio
cumque nihil impedit quo minus id quod maxime placeat facere possimus,
omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem
quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet
ut et voluptates repudiandae sint et molestiae non recusandae. Itaque
earum rerum hic tenetur a sapiente delectus, ut aut reiciendis
voluptatibus maiores alias consequatur aut perferendis doloribus
asperiores repellat."
</div>
</div>
JS:
$(function(){
$('.slider').on('click', '.slider-header', function(e){
$(e.delegateTarget).toggleClass('expanded');
});
});
CSS:
* {
box-sizing: border-box;
}
.slider {
position: relative;
overflow: hidden;
margin: 40px;
}
.slider .slider-header {
width: 100%;
height:40px;
text-align: center;
line-height: 40px;
background: green;
color: white;
cursor: pointer;
position: relative;
z-index: 2;
}
.slider .slider-body {
width: 100%;
padding: 20px;
position: relative;
z-index: 1;
background: red;
color: white;
text-align: center;
-ms-transform: translate3d(0, -140px, 0);
-o-transform: translate3d(0, -140px, 0);
-moz-transform: translate3d(0, -140px, 0);
transform: translate3d(0, -140px, 0);
opacity: 0;
-o-transition: all 0.2s ease-out;
-moz-transition: all 0.2s ease-out;
-webkit-transition: all 0.2s ease-out;
transition: all 0.2s ease-out;
}
.slider.expanded .slider-body {
-webkit=transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
First, you need to detect the height of your element at page load. Then set that height as the "max-height" css property.
Now you are able to slide up and down with some css and js :
window.addEventListener("load", () => {
var div = document.getElementById("slindingDiv");
// set max height
div.style.setProperty("max-height", div.offsetHeight + "px");
// default: hide
div.classList.add("up");
// button logic
document.getElementById("toggle").onclick = () => {
if (div.classList.contains("up")) {
div.classList.remove("up");
} else {
div.classList.add("up");
}
};
});
#slindingDiv {
transition: max-height 0.5s ease-in-out;
overflow: hidden;
background: antiquewhite;
/* YOU CAN PLAY WITH WIDTH */
width: 75%;
}
/* You just have to add this class to make it slide up */
#slindingDiv.up {
max-height: 0 !important;
}
<div id="slindingDiv">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus rutrum mi vel mauris ultricies, id vehicula mi hendrerit. Pellentesque placerat diam vel fermentum fermentum. Nulla eget odio a ipsum posuere dapibus. Ut sollicitudin tempor nibh, eu
convallis turpis iaculis tincidunt. Integer luctus ipsum vestibulum diam laoreet, at ornare felis tincidunt. Mauris dapibus diam ut ultrices ornare. Quisque nec risus in neque consequat efficitur vitae non turpis. Vivamus posuere sapien ac tellus
euismod volutpat eu id mauris. Nunc vel convallis nisi. Quisque convallis fringilla porttitor. Donec id consectetur nisi. Aliquam id dui ornare, efficitur erat sed, vestibulum nisi. Donec suscipit fringilla dolor, sed ullamcorper leo varius ac. Vestibulum</p>
</div>
<button id="toggle">Toggle slide</button>
Two pure CSS (no javascript) alternatives:
1 - Undercover checkboxes (allows multiple boxes opened at the same time):
input[type=checkbox] {
display: none;
}
jsfiddle DEMO #1
2 - Undercover radio buttons ("single choice" behavior):
input[type=radio] {
display: none;
}
jsfiddle DEMO #2
Javascript improved:
2b - Undercover radio buttons ("single choice" behavior) with deselect on a second click:
var allRadios = document.getElementsByName('image');
var booRadio;
var x = 0;
for(x = 0; x < allRadios.length; x++){
allRadios[x].onclick = function() {
if(booRadio == this){
this.checked = false;
booRadio = null;
}else{
booRadio = this;
}
};
}
jsfiddle DEMO #2B