最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to implement jQuery's slideDown() with unknown height in plain JS - Stack Overflow

programmeradmin2浏览0评论

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 0
Add a comment  | 

6 Answers 6

Reset to default 15 +100

Set 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

发布评论

评论列表(0)

  1. 暂无评论