我怎样才能过渡高度:0;高度:自动;用CSS?

时间:2010-08-18 02:50:35

标签: css css3 css-transitions

我正在尝试使用CSS过渡向下滑动<ul>

<ul>height: 0;开始。悬停时,高度设置为height:auto;。但是,这导致它只是出现,过渡,

如果我从height: 40px;height: auto;执行此操作,则会向上滑动到height: 0;,然后突然跳到正确的高度。

如果不使用JavaScript,我怎么能这样做?

#child0 {
  height: 0;
  overflow: hidden;
  background-color: #dedede;
  -moz-transition: height 1s ease;
  -webkit-transition: height 1s ease;
  -o-transition: height 1s ease;
  transition: height 1s ease;
}
#parent0:hover #child0 {
  height: auto;
}
#child40 {
  height: 40px;
  overflow: hidden;
  background-color: #dedede;
  -moz-transition: height 1s ease;
  -webkit-transition: height 1s ease;
  -o-transition: height 1s ease;
  transition: height 1s ease;
}
#parent40:hover #child40 {
  height: auto;
}
h1 {
  font-weight: bold;
}
The only difference between the two snippets of CSS is one has height: 0, the other height: 40.
<hr>
<div id="parent0">
  <h1>Hover me (height: 0)</h1>
  <div id="child0">Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>
  </div>
</div>
<hr>
<div id="parent40">
  <h1>Hover me (height: 40)</h1>
  <div id="child40">Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>
  </div>
</div>

59 个答案:

答案 0 :(得分:2453)

在转化中使用max-height,而不是height。并将max-height上的值设置为比您的盒子更大的值。

请参阅Chris Jordan在另一个JSFiddle demo提供的answer

#menu #list {
    max-height: 0;
    transition: max-height 0.15s ease-out;
    overflow: hidden;
    background: #d5d5d5;
}

#menu:hover #list {
    max-height: 500px;
    transition: max-height 0.25s ease-in;
}
<div id="menu">
    <a>hover me</a>
    <ul id="list">
        <!-- Create a bunch, or not a bunch, of li's to see the timing. -->
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
</div>

答案 1 :(得分:268)

您应该使用scaleY。

HTML:

<p>Here (scaleY(1))</p>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

CSS:

ul {
    background-color: #eee;
    transform: scaleY(0);    
    transform-origin: top;
    transition: transform 0.26s ease;
}

p:hover ~ ul {
    transform: scaleY(1);
}

我在jsfiddle http://jsfiddle.net/dotnetCarpenter/PhyQc/9/上制作了上述代码的供应商前缀版本,并将您的jsfiddle改为使用scaleY而不是height http://jsfiddle.net/dotnetCarpenter/7cnfc/206/

答案 2 :(得分:183)

当所涉及的高度之一为auto时,您无法在高度上设置动画,您必须设置两个明确的高度。

答案 3 :(得分:101)

我一直使用的解决方案是首先淡出,然后缩小font-sizepaddingmargin值。它与wipe看起来不一样,但它没有静态heightmax-height

工作示例:

/* final display */
#menu #list {
    margin: .5em 1em;
    padding: 1em;
}

/* hide */
#menu:not(:hover) #list {
    font-size: 0;
    margin: 0;
    opacity: 0;
    padding: 0;
    /* fade out, then shrink */
    transition: opacity .25s,
                font-size .5s .25s,
                margin .5s .25s,
                padding .5s .25s;
}

/* reveal */
#menu:hover #list {
    /* unshrink, then fade in */
    transition: font-size .25s,
                margin .25s,
                padding .25s,
                opacity .5s .25s;
}
<div id="menu">
    <b>hover me</b>
    <ul id="list">
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
</div>

<p>Another paragraph...</p>

答案 4 :(得分:74)

你可以用一点点非语义的jiggery-pokery。我通常的方法是设置外部DIV的高度,该外部DIV具有单个子项,这是一种仅用于测量内容高度的无样式DIV。

function growDiv() {
  var growDiv = document.getElementById('grow');
  if (growDiv.clientHeight) {
    growDiv.style.height = 0;
  } else {
    var wrapper = document.querySelector('.measuringWrapper');
    growDiv.style.height = wrapper.clientHeight + "px";
  }
}
#grow {
  -moz-transition: height .5s;
  -ms-transition: height .5s;
  -o-transition: height .5s;
  -webkit-transition: height .5s;
  transition: height .5s;
  height: 0;
  overflow: hidden;
  outline: 1px solid red;
}
<input type="button" onclick="growDiv()" value="grow">
<div id='grow'>
  <div class='measuringWrapper'>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
  </div>
</div>

有人希望能够省去.measuringWrapper并将DIV的高度设置为自动并具有该动画,但这似乎不起作用(高度设置,但没有动画发生)。

function growDiv() {
  var growDiv = document.getElementById('grow');
  if (growDiv.clientHeight) {
    growDiv.style.height = 0;
  } else {
    growDiv.style.height = 'auto';
  }
}
#grow {
  -moz-transition: height .5s;
  -ms-transition: height .5s;
  -o-transition: height .5s;
  -webkit-transition: height .5s;
  transition: height .5s;
  height: 0;
  overflow: hidden;
  outline: 1px solid red;
}
<input type="button" onclick="growDiv()" value="grow">
<div id='grow'>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
</div>

我的解释是动画运行需要一个显式高度。当高度(开始或结束高度)为auto时,您无法获得高度动画。

答案 5 :(得分:71)

我知道这是这个问题的三十分之一的答案,但我认为这是值得的,所以这里有。这是仅限CSS 解决方案,具有以下属性:

  • 开始时没有延迟,过渡不会提前停止。在两个方向(展开和折叠)中,如果在CSS中指定300毫秒的转换持续时间,则转换需要300毫秒(周期)。
  • 它正在转换实际高度(与transform: scaleY(0)不同),因此如果在可折叠元素之后有内容,它会做正确的事情。
  • 虽然(和其他解决方案一样)魔术数字(比如&#34;选择一个高于你的盒子的长度&#34;),它&#39;如果你的假设最终错了,那就不是致命的。在这种情况下,转换可能看起来并不令人惊讶,但在转换之前和之后,这不是问题:在扩展(height: auto)状态下,整个内容始终具有正确的高度(例如,如果您选择一个结果证明max-height太低了。在折叠状态下,高度应该为零。

演示

这是一个包含三个可折叠元素的演示,所有元素都具有不同的高度,它们都使用相同的CSS。您可能需要点击&#34;整页&#34;点击&#34;运行代码段&#34;。请注意,JavaScript仅切换collapsed CSS类,不涉及测量。 (你可以使用复选框或:target完成没有任何JavaScript的精确演示。另请注意,负责转换的CSS部分非常简短,HTML只需要一个额外的包装元素。

&#13;
&#13;
$(function () {
  $(".toggler").click(function () {
    $(this).next().toggleClass("collapsed");
    $(this).toggleClass("toggled"); // this just rotates the expander arrow
  });
});
&#13;
.collapsible-wrapper {
  display: flex;
  overflow: hidden;
}
.collapsible-wrapper:after {
  content: '';
  height: 50px;
  transition: height 0.3s linear, max-height 0s 0.3s linear;
  max-height: 0px;
}
.collapsible {
  transition: margin-bottom 0.3s cubic-bezier(0, 0, 0, 1);
  margin-bottom: 0;
  max-height: 1000000px;
}
.collapsible-wrapper.collapsed > .collapsible {
  margin-bottom: -2000px;
  transition: margin-bottom 0.3s cubic-bezier(1, 0, 1, 1),
              visibility 0s 0.3s, max-height 0s 0.3s;
  visibility: hidden;
  max-height: 0;
}
.collapsible-wrapper.collapsed:after
{
  height: 0;
  transition: height 0.3s linear;
  max-height: 50px;
}

/* END of the collapsible implementation; the stuff below
   is just styling for this demo */

#container {
  display: flex;
  align-items: flex-start;
  max-width: 1000px;
  margin: 0 auto;
}  


.menu {
  border: 1px solid #ccc;
  box-shadow: 0 1px 3px rgba(0,0,0,0.5);
  margin: 20px;

  
}

.menu-item {
  display: block;
  background: linear-gradient(to bottom, #fff 0%,#eee 100%);
  margin: 0;
  padding: 1em;
  line-height: 1.3;
}
.collapsible .menu-item {
  border-left: 2px solid #888;
  border-right: 2px solid #888;
  background: linear-gradient(to bottom, #eee 0%,#ddd 100%);
}
.menu-item.toggler {
  background: linear-gradient(to bottom, #aaa 0%,#888 100%);
  color: white;
  cursor: pointer;
}
.menu-item.toggler:before {
  content: '';
  display: block;
  border-left: 8px solid white;
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
  width: 0;
  height: 0;
  float: right;
  transition: transform 0.3s ease-out;
}
.menu-item.toggler.toggled:before {
  transform: rotate(90deg);
}

body { font-family: sans-serif; font-size: 14px; }

*, *:after {
  box-sizing: border-box;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="container">
  <div class="menu">
    <div class="menu-item">Something involving a holodeck</div>
    <div class="menu-item">Send an away team</div>
    <div class="menu-item toggler">Advanced solutions</div>
    <div class="collapsible-wrapper collapsed">
      <div class="collapsible">
        <div class="menu-item">Separate saucer</div>
        <div class="menu-item">Send an away team that includes the captain (despite Riker's protest)</div>
        <div class="menu-item">Ask Worf</div>
        <div class="menu-item">Something involving Wesley, the 19th century, and a holodeck</div>
        <div class="menu-item">Ask Q for help</div>
      </div>
    </div>
    <div class="menu-item">Sweet-talk the alien aggressor</div>
    <div class="menu-item">Re-route power from auxiliary systems</div>
  </div>

  <div class="menu">
    <div class="menu-item">Something involving a holodeck</div>
    <div class="menu-item">Send an away team</div>
    <div class="menu-item toggler">Advanced solutions</div>
    <div class="collapsible-wrapper collapsed">
      <div class="collapsible">
        <div class="menu-item">Separate saucer</div>
        <div class="menu-item">Send an away team that includes the captain (despite Riker's protest)</div>
      </div>
    </div>
    <div class="menu-item">Sweet-talk the alien aggressor</div>
    <div class="menu-item">Re-route power from auxiliary systems</div>
  </div>

  <div class="menu">
    <div class="menu-item">Something involving a holodeck</div>
    <div class="menu-item">Send an away team</div>
    <div class="menu-item toggler">Advanced solutions</div>
    <div class="collapsible-wrapper collapsed">
      <div class="collapsible">
        <div class="menu-item">Separate saucer</div>
        <div class="menu-item">Send an away team that includes the captain (despite Riker's protest)</div>
        <div class="menu-item">Ask Worf</div>
        <div class="menu-item">Something involving Wesley, the 19th century, and a holodeck</div>
        <div class="menu-item">Ask Q for help</div>
        <div class="menu-item">Separate saucer</div>
        <div class="menu-item">Send an away team that includes the captain (despite Riker's protest)</div>
        <div class="menu-item">Ask Worf</div>
        <div class="menu-item">Something involving Wesley, the 19th century, and a holodeck</div>
        <div class="menu-item">Ask Q for help</div>
      </div>
    </div>
    <div class="menu-item">Sweet-talk the alien aggressor</div>
    <div class="menu-item">Re-route power from auxiliary systems</div>
  </div>

</div>
&#13;
&#13;
&#13;

它是如何工作的?

事实上,实现两个转换。其中一个将margin-bottom从0px(处于展开状态)转换为折叠状态下的-2000px(类似于this answer)。这里的2000是第一个神奇的数字,它基于你的盒子不会高于此值的假设(2000像素似乎是一个合理的选择)。

单独使用margin-bottom转换本身有两个问题:

  • 如果你实际上有一个超过2000像素的盒子,那么margin-bottom: -2000px不会隐藏所有内容 - 即使在折叠的情况下,它也会是可见的东西。这是我们稍后会做的一个小修复。
  • 如果实际的盒子是1000像素高,并且你的转换是300ms长,那么可见转换在大约150ms后已经结束(或者,相反的方向,开始时间晚150ms) )。

修复第二个问题是第二个过渡进入的地方,这个过渡在概念上针对包装的最小高度(&#34;概念上&#34;因为我们是实际上没有使用min-height属性;稍后会详细介绍。

这是一个动画,展示了如何将底部边距过渡与最小高度过渡相结合,两者具有相同的持续时间,为我们提供了从全高度到零高度的组合过渡,具有相同的持续时间。

animation as described above

左侧栏显示负底部边缘如何向下推动底部,降低可见高度。中间条显示最小高度如何确保在崩溃的情况下,过渡不会提前结束,并且在扩展的情况下,过渡不会延迟。右侧栏显示两者的组合如何使盒子在正确的时间内从全高度过渡到零高度。

对于我的演示,我已经确定50px为最小高度值。这是第二个神奇的数字,它应该低于框#39;高度永远都是。 50px似乎也是合理的;你似乎不太可能经常想让一个元素折叠起来甚至不到50像素高。

正如您在动画中看到的那样,所产生的过渡是连续的,但它是不可微分的 - 当最小高度等于由下边距调整的全高时,速度会突然改变。这在动画中非常明显,因为它对两个过渡使用线性定时功能,并且因为整个过渡非常慢。在实际情况下(我的演示在顶部),转换只需要300毫秒,底部边距转换不是线性的。我已经为这两种转换玩了很多不同的计时功能,而我最终感觉它们最适合各种各样的情况。

还有两个问题需要解决:

  1. 从上面开始,高度超过2000像素的盒子在折叠状态下不会被完全隐藏,
  2. 和相反的问题,在非隐藏的情况下,即使转换没有运行,高度小于50像素的框也太高,因为最小高度使它们保持在50像素。
  3. 我们通过在折叠的情况下为容器元素max-height: 0提供0s 0.3s转换来解决第一个问题。这意味着它并非真正的过渡,但max-height会延迟应用;它只适用于转换结束后。为了使其正常工作,我们还需要为相反的非折叠状态选择数字max-height。但与2000px的情况不同,选择太大的数字会影响转换的质量,在这种情况下,它确实无关紧要。因此,我们可以选择一个非常高的数字,以便我们知道没有任何高度可以接近这一点。我选了一百万像素。如果您觉得可能需要支持高度超过一百万像素的内容,那么1)对不起,2)只需添加几个零。

    第二个问题是我们实际上没有使用min-height进行最小高度转换的原因。相反,容器中有一个::after伪元素,其height从50px转换为零。这与min-height具有相同的效果:它不会让容器收缩到伪元素当前所具有的任何高度以下。但由于我们正在使用height,而不是min-height,我们现在可以使用max-height(再次应用延迟)来设置伪元素的实际高度转换结束后为零,确保至少在转换之外,即使是小元素也具有正确的高度。由于min-heightstronger而不是max-height,如果我们使用容器min-height而不是伪元素,这将无法工作height。就像上一段中的max-height一样,此max-height也需要一个过渡另一端的值。但在这种情况下,我们可以选择50px。

    在Chrome(Win,Mac,Android,iOS),Firefox(Win,Mac,Android),Edge,IE11中测试过(除了我的演示中的flexbox布局问题,我没有打扰调试),以及Safari(Mac,iOS)。说到flexbox,应该可以在不使用任何flexbox的情况下完成这项工作;事实上,我认为你几乎可以让所有东西都在IE7中运行 - 除了你没有获得CSS转换这一事实,这使得它成为一种毫无意义的练习。

答案 6 :(得分:48)

使用CSS3过渡动画高度的可视化解决方法是为填充设置动画。

你没有完全获得完全擦除效果,但是使用转换持续时间和填充值可以让你足够接近。如果您不想明确设置height / max-height,那么这应该是您正在寻找的。

div {
    height: 0;
    overflow: hidden;
    padding: 0 18px;
    -webkit-transition: all .5s ease;
       -moz-transition: all .5s ease;
            transition: all .5s ease;
}
div.animated {
    height: auto;
    padding: 24px 18px;
}

http://jsfiddle.net/catharsis/n5XfG/17/(在stesband上方jsFiddle上面咆哮)

答案 7 :(得分:46)

我的解决方法是将max-height转换为精确内容高度以获得漂亮的平滑动画,然后使用transitionEnd回调将max-height设置为9999px,以便内容可以自由调整大小。

var content = $('#content');
content.inner = $('#content .inner'); // inner div needed to get size of content when closed

// css transition callback
content.on('transitionEnd webkitTransitionEnd transitionend oTransitionEnd msTransitionEnd', function(e){
    if(content.hasClass('open')){
        content.css('max-height', 9999); // try setting this to 'none'... I dare you!
    }
});

$('#toggle').on('click', function(e){
    content.toggleClass('open closed');
    content.contentHeight = content.outerHeight();
    
    if(content.hasClass('closed')){
        
        // disable transitions & set max-height to content height
        content.removeClass('transitions').css('max-height', content.contentHeight);
        setTimeout(function(){
            
            // enable & start transition
            content.addClass('transitions').css({
                'max-height': 0,
                'opacity': 0
            });
            
        }, 10); // 10ms timeout is the secret ingredient for disabling/enabling transitions
        // chrome only needs 1ms but FF needs ~10ms or it chokes on the first animation for some reason
        
    }else if(content.hasClass('open')){  
        
        content.contentHeight += content.inner.outerHeight(); // if closed, add inner height to content height
        content.css({
            'max-height': content.contentHeight,
            'opacity': 1
        });
        
    }
});
.transitions {
    transition: all 0.5s ease-in-out;
    -webkit-transition: all 0.5s ease-in-out;
    -moz-transition: all 0.5s ease-in-out;
}

body {
    font-family:Arial;
    line-height: 3ex;
}
code {
    display: inline-block;
    background: #fafafa;
    padding: 0 1ex;
}
#toggle {
    display:block;
    padding:10px;
    margin:10px auto;
    text-align:center;
    width:30ex;
}
#content {
    overflow:hidden;
    margin:10px;
    border:1px solid #666;
    background:#efefef;
    opacity:1;
}
#content .inner {
    padding:10px;
    overflow:auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div id="content" class="open">
    <div class="inner">
        <h3>Smooth CSS Transitions Between <code>height: 0</code> and <code>height: auto</code></h3>
        <p>A clever workaround is to use <code>max-height</code> instead of <code>height</code>, and set it to something bigger than your content. Problem is the browser uses this value to calculate transition duration. So if you set it to <code>max-height: 1000px</code> but the content is only 100px high, the animation will be 10x too fast.</p>
        <p>Another option is to measure the content height with JS and transition to that fixed value, but then you have to keep track of the content and manually resize it if it changes.</p>
        <p>This solution is a hybrid of the two - transition to the measured content height, then set it to <code>max-height: 9999px</code> after the transition for fluid content sizing.</p>
    </div>
</div>

<br />

<button id="toggle">Challenge Accepted!</button>

答案 8 :(得分:35)

接受的答案适用于大多数情况,但当div的高度变化很大时,它不能很好地工作 - 动画速度不依赖于内容的实际高度,它可以看起来不稳定。

您仍然可以使用CSS执行实际动画,但您需要使用JavaScript来计算项目的高度,而不是尝试使用auto。不需要jQuery,但如果你想要兼容性(可以在Chrome的最新版本中使用:),你可能需要稍微修改一下j。)。

&#13;
&#13;
window.toggleExpand = function(element) {
    if (!element.style.height || element.style.height == '0px') { 
        element.style.height = Array.prototype.reduce.call(element.childNodes, function(p, c) {return p + (c.offsetHeight || 0);}, 0) + 'px';
    } else {
        element.style.height = '0px';
    }
}
&#13;
#menu #list {
    height: 0px;
    transition: height 0.3s ease;
    background: #d5d5d5;
    overflow: hidden;
}
&#13;
<div id="menu">
    <input value="Toggle list" type="button" onclick="toggleExpand(document.getElementById('list'));">
    <ul id="list">
        <!-- Works well with dynamically-sized content. -->
        <li>item</li>
        <li><div style="height: 100px; width: 100px; background: red;"></div></li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
</div>
&#13;
&#13;
&#13;

答案 9 :(得分:26)

对每个州使用max-height不同的转换缓和和延迟。

HTML:

<a href="#" id="trigger">Hover</a>
<ul id="toggled">
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
<ul>

CSS:

#toggled{
    max-height: 0px;
    transition: max-height .8s cubic-bezier(0, 1, 0, 1) -.1s;
}

#trigger:hover + #toggled{
    max-height: 9999px;
    transition-timing-function: cubic-bezier(0.5, 0, 1, 0); 
    transition-delay: 0s;
}

参见示例:http://jsfiddle.net/0hnjehjc/1/

答案 10 :(得分:25)

没有硬编码值。

没有JavaScript。

没有近似值。

诀窍是使用隐藏的&amp; amp;重复div以使浏览器了解100%的含义。

只要您能够复制要设置动画的元素的DOM,此方法就适用。

&#13;
&#13;
.outer {
  border: dashed red 1px;
  position: relative;
}

.dummy {
  visibility: hidden;
}

.real {
  position: absolute;
  background: yellow;
  height: 0;
  transition: height 0.5s;
  overflow: hidden;
}

.outer:hover>.real {
  height: 100%;
}
&#13;
Hover over the box below:
<div class="outer">
  <!-- The actual element that you'd like to animate -->
  <div class="real">
unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable
content unpredictable content unpredictable content unpredictable content
  </div>
  <!-- An exact copy of the element you'd like to animate. -->
  <div class="dummy" aria-hidden="true">
unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable
content unpredictable content unpredictable content unpredictable content
  </div>
</div>
&#13;
&#13;
&#13;

答案 11 :(得分:24)

几乎没有提及Element.scrollHeight属性在这里很有用,但仍然可以用于纯CSS过渡。该物业始终包含&#34; full&#34;元素的高度,无论其内容是否以及如何因折叠高度而溢出(例如height: 0)。

因此,对于height: 0(实际完全折叠)元素,其正常&#34;正常&#34;或者&#34;完整&#34;高度仍可通过其scrollHeight值(总是像素长度)随时可用。

对于这样的元素,假设它已经具有像(根据原始问题使用ul):

ul {
    height: 0;
    transition: height 1s; /* An example transition. */
}

我们可以触发所需的动画&#34;扩展&#34;高度,仅使用CSS,类似下面的内容(这里假设ul变量引用列表):

ul.style.height = ul.scrollHeight + "px";

那就是它。如果您需要折叠列表,则以下两个语句中的任何一个都将执行:

ul.style.height = "0";
ul.style.removeProperty("height");

我的特殊用例主要围绕着未知且通常相当长的动画列表,所以我不习惯在一个任意的&#34;足够大的&#34; heightmax-height规范,以及您突然需要滚动的截止内容或内容(例如,如果overflow: auto)。此外,基于max-height的解决方案可以简化缓和时间,因为使用的高度可能比max-height达到9999px所需的时间更快达到最大值。随着屏幕分辨率的增长,像9999px这样的像素长度在我的嘴里留下了不好的味道。在我看来,这个特殊的解决方案以优雅的方式解决了这个问题。

最后,这里希望CSS的未来版本能够解决作者的问题。需要更优雅地做这些事情 - 重新审视&#34;计算&#34;的概念。 vs&#34;使用&#34;并且&#34;已解决&#34;值,并考虑转换是否应该应用于计算值,包括widthheight的转换(目前有一些特殊处理)。

答案 12 :(得分:21)

正如我发布的那样,已经有超过30个答案,但我觉得我的答案在杰克已经accepted answer上得到了改善。

我不满足于简单地使用max-height和CSS3过渡所引起的问题,因为很多评论者指出,你必须将max-height值设置得非常接近实际高度,或者你'我会得到一个延迟。有关该问题的示例,请参阅此JSFiddle

为了解决这个问题(虽然仍然没有使用JavaScript),我添加了另一个转换transform: translateY CSS值的HTML元素。

这意味着使用了max-heighttranslateYmax-height允许元素按下它下方的元素,而translateY则提供我们想要的“即时”效果。 max-height的问题仍然存在,但其影响有所减轻。 这意味着您可以为max-height值设置更大的高度,并减少对它的担忧。

总体好处是,在转换回(崩溃)时,用户会立即看到translateY动画,因此max-height占用的时间并不重要。

<强> Solution as Fiddle

body {
  font-family: sans-serif;
}

.toggle {
  position: relative;
  border: 2px solid #333;
  border-radius: 3px;
  margin: 5px;
  width: 200px;
}

.toggle-header {
  margin: 0;
  padding: 10px;
  background-color: #333;
  color: white;
  text-align: center;
  cursor: pointer;
}

.toggle-height {
  background-color: tomato;
  overflow: hidden;
  transition: max-height .6s ease;
  max-height: 0;
}

.toggle:hover .toggle-height {
  max-height: 1000px;
}

.toggle-transform {
  padding: 5px;
  color: white;
  transition: transform .4s ease;
  transform: translateY(-100%);
}

.toggle:hover .toggle-transform {
  transform: translateY(0);
}
<div class="toggle">
  <div class="toggle-header">
    Toggle!
  </div>
  <div class="toggle-height">
    <div class="toggle-transform">
      <p>Content!</p>
      <p>Content!</p>
      <p>Content!</p>
      <p>Content!</p>
    </div>
  </div>
</div>

<div class="toggle">
  <div class="toggle-header">
    Toggle!
  </div>
  <div class="toggle-height">
    <div class="toggle-transform">
      <p>Content!</p>
      <p>Content!</p>
      <p>Content!</p>
      <p>Content!</p>
    </div>
  </div>
</div>

答案 13 :(得分:17)

好的,所以我想我想出了一个超级简单的答案...... 没有max-height,使用relative定位,适用于li元素,&amp;是纯CSS。 除了Firefox之外,我还没有测试任何东西,但它应该适用于所有浏览器。

FIDDLE:http://jsfiddle.net/n5XfG/2596/

CSS

.wrap { overflow:hidden; }

.inner {
            margin-top:-100%;
    -webkit-transition:margin-top 500ms;
            transition:margin-top 500ms;
}

.inner.open { margin-top:0px; }

HTML

<div class="wrap">
    <div class="inner">Some Cool Content</div>
</div>

答案 14 :(得分:14)

编辑:向下滚动以获取更新的答案
我正在制作一个下拉列表,看到这个帖子...许多不同的答案,但我决定分享我的下拉列表,...它不完美,但至少它只会使用css下拉!我一直在使用transform:translateY(y)将列表转换为视图...
您可以在测试中看到更多内容 http://jsfiddle.net/BVEpc/4/
我已将div放在每个li后面,因为我的下拉列表来自并正确显示它们需要,我的div代码是:

#menu div {
    transition: 0.5s 1s;
    z-index:-1;
    -webkit-transform:translateY(-100%);
    -webkit-transform-origin: top;
}

和悬停是:

#menu > li:hover div {
    transition: 0.5s;
    -webkit-transform:translateY(0);
}

并且因为ul高度被设置为它可以覆盖你的身体内容的内容,这就是为什么我为ul做了这个:

 #menu ul {
    transition: 0s 1.5s;
    visibility:hidden;
    overflow:hidden;
}

并悬停:

#menu > li:hover ul {
     transition:none;
     visibility:visible;
}

转换后的第二次是延迟,并且在我的下拉列表被大幅关闭后它将被隐藏...
希望以后有人能从中受益。

编辑:我真的不相信人们实际使用这个原型!这个下拉菜单只适用于一个子菜单,这就是全部!! 我已经更新了一个更好的,可以在IE 8支持的情况下为ltr和rtl方向提供两个子菜单。
Fiddle for LTR
Fiddle for RTL
希望有人在将来发现这个有用。

答案 15 :(得分:12)

您可以从高度:0过渡到高度:自动,同时提供最小高度和最大高度。

div.stretchy{
    transition: 1s linear;
}

div.stretchy.hidden{
    height: 0;
}

div.stretchy.visible{
    height: auto;
    min-height:40px;
    max-height:400px;
}

答案 16 :(得分:10)

我认为我提出了一个非常可靠的解决方案

OK!我知道这个问题与互联网一样古老,但我认为我有一个解决方案,我变成了plugin called mutant-transition。每当DOM发生变化时,我的解决方案都会为被跟踪元素设置style=""属性。最终结果是你可以使用好的ole CSS进行转换,而不是使用hacky修复程序或特殊的javascript。您唯一要做的就是使用data-mutant-attributes="X"设置要跟踪的元素。

<div data-mutant-attributes="height">                                                                      
        This is an example with mutant-transition                                                                                                          
    </div>

多数民众赞成!此解决方案使用MutationObserver来跟踪DOM中的更改。因此,您不必设置任何内容或使用javascript手动设置动画。自动跟踪更改。但是,因为它使用MutationObserver,所以这只会在IE11 +中进行转换。

<强>小提琴!

答案 17 :(得分:10)

Flexbox解决方案

优点:

  • 简单
  • 没有JS
  • 平稳过渡

缺点:

  • 元素需要放在固定高度的flex容器中

它的工作方式是始终使用flex-basis:对包含内容的元素执行auto,然后转换flex-grow和flex-shrink。

编辑:改进的JS小提琴灵感来自Xbox One界面。

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  transition: 0.25s;
  font-family: monospace;
}

body {
  margin: 10px 0 0 10px;
}

.box {
  width: 150px;
  height: 150px;
  margin: 0 2px 10px 0;
  background: #2d333b;
  border: solid 10px #20262e;
  overflow: hidden;
  display: inline-flex;
  flex-direction: column;
}

.space {
  flex-basis: 100%;
  flex-grow: 1;
  flex-shrink: 0;    
}

p {
  flex-basis: auto;
  flex-grow: 0;
  flex-shrink: 1;
  background: #20262e;
  padding: 10px;
  width: 100%;
  text-align: left;
  color: white;
}

.box:hover .space {
  flex-grow: 0;
  flex-shrink: 1;
}
  
.box:hover p {
  flex-grow: 1;
  flex-shrink: 0;    
}
<div class="box">
  <div class="space"></div>
  <p>
    Super Metroid Prime Fusion
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    Resident Evil 2 Remake
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    Yolo The Game
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    Final Fantasy 7 Remake + All Additional DLC + Golden Tophat
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    DerpVille
  </p>
</div>

JS Fiddle

答案 18 :(得分:7)

这是一种从任何起始高度(包括0)过渡到自动(完整大小和灵活)的方法,无需基于每个节点的硬件代码或任何初始化的用户代码:https://github.com/csuwildcat/transition-auto。这基本上是你想要的圣杯,我相信 - &gt; http://codepen.io/csuwldcat/pen/kwsdF。只需将以下JS文件打入您的页面,之后您需要做的就是从要扩展和收缩的节点添加/删除单个布尔属性 - reveal=""

在您包含示例代码下方的代码块后,您需要以用户身份完成所有操作:

/*** Nothing out of the ordinary in your styles ***/
<style>
    div {
        height: 0;
        overflow: hidden;
        transition: height 1s;
    }
</style>

/*** Just add and remove one attribute and transition to/from auto! ***/

<div>
    I have tons of content and I am 0px in height you can't see me...
</div>

<div reveal>
     I have tons of content and I am 0px in height you can't see me...
     but now that you added the 'reveal' attribute, 
     I magically transitioned to full height!...
</div>

这是要包含在您的网页中的代码块,之后,它都是肉汁:

将此JS文件放入您的页面 - 这一切都是Just Works™

/ *身高代码:auto;过渡* /

(function(doc){

/* feature detection for browsers that report different values for scrollHeight when an element's overflow is hidden vs visible (Firefox, IE) */
var test = doc.documentElement.appendChild(doc.createElement('x-reveal-test'));
    test.innerHTML = '-';
    test.style.cssText = 'display: block !important; height: 0px !important; padding: 0px !important; font-size: 0px !important; border-width: 0px !important; line-height: 1px !important; overflow: hidden !important;';
var scroll = test.scrollHeight || 2;
doc.documentElement.removeChild(test);

var loading = true,
    numReg = /^([0-9]*\.?[0-9]*)(.*)/,
    skipFrame = function(fn){
      requestAnimationFrame(function(){
        requestAnimationFrame(fn);
      });
    },
    /* 2 out of 3 uses of this function are purely to work around Chrome's catastrophically busted implementation of auto value CSS transitioning */
    revealFrame = function(el, state, height){
        el.setAttribute('reveal-transition', 'frame');
        el.style.height = height;
        skipFrame(function(){
            el.setAttribute('reveal-transition', state);
            el.style.height = '';
        });
    },
    transitionend = function(e){
      var node = e.target;
      if (node.hasAttribute('reveal')) {
        if (node.getAttribute('reveal-transition') == 'running') revealFrame(node, 'complete', '');
      } 
      else {
        node.removeAttribute('reveal-transition');
        node.style.height = '';
      }
    },
    animationstart = function(e){
      var node = e.target,
          name = e.animationName;   
      if (name == 'reveal' || name == 'unreveal') {

        if (loading) return revealFrame(node, 'complete', 'auto');

        var style = getComputedStyle(node),
            offset = (Number(style.paddingTop.match(numReg)[1])) +
                     (Number(style.paddingBottom.match(numReg)[1])) +
                     (Number(style.borderTopWidth.match(numReg)[1])) +
                     (Number(style.borderBottomWidth.match(numReg)[1]));

        if (name == 'reveal'){
          node.setAttribute('reveal-transition', 'running');
          node.style.height = node.scrollHeight - (offset / scroll) + 'px';
        }
        else {
            if (node.getAttribute('reveal-transition') == 'running') node.style.height = '';
            else revealFrame(node, 'running', node.scrollHeight - offset + 'px');
        }
      }
    };

doc.addEventListener('animationstart', animationstart, false);
doc.addEventListener('MSAnimationStart', animationstart, false);
doc.addEventListener('webkitAnimationStart', animationstart, false);
doc.addEventListener('transitionend', transitionend, false);
doc.addEventListener('MSTransitionEnd', transitionend, false);
doc.addEventListener('webkitTransitionEnd', transitionend, false);

/*
    Batshit readyState/DOMContentLoaded code to dance around Webkit/Chrome animation auto-run weirdness on initial page load.
    If they fixed their code, you could just check for if(doc.readyState != 'complete') in animationstart's if(loading) check
*/
if (document.readyState == 'complete') {
    skipFrame(function(){
        loading = false;
    });
}
else document.addEventListener('DOMContentLoaded', function(e){
    skipFrame(function(){
        loading = false;
    });
}, false);

/* Styles that allow for 'reveal' attribute triggers */
var styles = doc.createElement('style'),
    t = 'transition: none; ',
    au = 'animation: reveal 0.001s; ',
    ar = 'animation: unreveal 0.001s; ',
    clip = ' { from { opacity: 0; } to { opacity: 1; } }',
    r = 'keyframes reveal' + clip,
    u = 'keyframes unreveal' + clip;

styles.textContent = '[reveal] { -ms-'+ au + '-webkit-'+ au +'-moz-'+ au + au +'}' +
    '[reveal-transition="frame"] { -ms-' + t + '-webkit-' + t + '-moz-' + t + t + 'height: auto; }' +
    '[reveal-transition="complete"] { height: auto; }' +
    '[reveal-transition]:not([reveal]) { -webkit-'+ ar +'-moz-'+ ar + ar +'}' +
    '@-ms-' + r + '@-webkit-' + r + '@-moz-' + r + r +
    '@-ms-' + u +'@-webkit-' + u + '@-moz-' + u + u;

doc.querySelector('head').appendChild(styles);

})(document);

/ * DEMO代码* /

    document.addEventListener('click', function(e){
      if (e.target.nodeName == 'BUTTON') {
        var next = e.target.nextElementSibling;
        next.hasAttribute('reveal') ? next.removeAttribute('reveal') : next.setAttribute('reveal', '');
      }
    }, false);

答案 19 :(得分:7)

Jake对最大高度动画的回答非常好,但是我发现设置一个大的最大高度引起的延迟很烦人。

可以将可折叠内容移动到内部div中,并通过获取内部div的高度来计算最大高度(通过JQuery,它可以是outerHeight())。

$('button').bind('click', function(e) { 
  e.preventDefault();
  w = $('#outer');
  if (w.hasClass('collapsed')) {
    w.css({ "max-height": $('#inner').outerHeight() + 'px' });
  } else {
    w.css({ "max-height": "0px" });
  }
  w.toggleClass('collapsed');
});

这是一个jsfiddle链接:http://jsfiddle.net/pbatey/duZpT

这里有一个jsfiddle,其中包含绝对最少量的代码:http://jsfiddle.net/8ncjjxh8/

答案 20 :(得分:5)

我意识到这个帖子已经老了,但它在某些Google搜索中排名很高,所以我觉得值得更新。

您也可以获取/设置元素自己的高度:

var load_height = document.getElementById('target_box').clientHeight;
document.getElementById('target_box').style.height = load_height + 'px';

您应该在内联脚本标记中的target_box结束标记之后立即转储此Javascript。

答案 21 :(得分:5)

扩展@jake的答案,过渡将一直到最大高度值,导致极快的动画 - 如果你设置两者的过渡:悬停和关闭你可以再多一点控制疯狂的速度

所以li:hover是指鼠标进入状态,然后非hovered属性的转换将是鼠标离开。

希望这会有所帮助。

例如:

.sidemenu li ul {
   max-height: 0px;
   -webkit-transition: all .3s ease;
   -moz-transition: all .3s ease;
   -o-transition: all .3s ease;
   -ms-transition: all .3s ease;
   transition: all .3s ease;
}
.sidemenu li:hover ul {
    max-height: 500px;
    -webkit-transition: all 1s ease;
   -moz-transition: all 1s ease;
   -o-transition: all 1s ease;
   -ms-transition: all 1s ease;
   transition: all 1s ease;
}
/* Adjust speeds to the possible height of the list */

这是一个小提琴:http://jsfiddle.net/BukwJ/

答案 22 :(得分:4)

这是我刚刚与jQuery结合使用的解决方案。这适用于以下HTML结构:

<nav id="main-nav">
    <ul>
        <li>
            <a class="main-link" href="yourlink.html">Link</a>
            <ul>
                <li><a href="yourlink.html">Sub Link</a></li>
            </ul>
        </li>
    </ul>
</nav>

和功能:

    $('#main-nav li ul').each(function(){
        $me = $(this);

        //Count the number of li elements in this UL
        var liCount = $me.find('li').size(),
        //Multiply the liCount by the height + the margin on each li
            ulHeight = liCount * 28;

        //Store height in the data-height attribute in the UL
        $me.attr("data-height", ulHeight);
    });

然后,您可以使用点击功能使用css()

设置和删除高度
$('#main-nav li a.main-link').click(function(){
    //Collapse all submenus back to 0
    $('#main-nav li ul').removeAttr('style');

    $(this).parent().addClass('current');

    //Set height on current submenu to it's height
    var $currentUl = $('li.current ul'),
        currentUlHeight = $currentUl.attr('data-height');
})

CSS:

#main-nav li ul { 
    height: 0;
    position: relative;
    overflow: hidden;
    opacity: 0; 
    filter: alpha(opacity=0); 
    -ms-filter: "alpha(opacity=0)";
    -khtml-opacity: 0; 
    -moz-opacity: 0;
    -webkit-transition: all .6s ease-in-out;
    -moz-transition: all .6s ease-in-out;
    -o-transition: all .6s ease-in-out;
    -ms-transition: all .6s ease-in-out;
    transition: all .6s ease-in-out;
}

#main-nav li.current ul {
    opacity: 1.0; 
    filter: alpha(opacity=100); 
    -ms-filter: "alpha(opacity=100)";
    -khtml-opacity: 1.0; 
    -moz-opacity: 1.0;
}

.ie #main-nav li.current ul { height: auto !important }

#main-nav li { height: 25px; display: block; margin-bottom: 3px }

答案 23 :(得分:4)

我最近在max-height元素上转换li而不是包裹ul

原因是小max-heights的延迟与大max-heights相比远不那么明显(如果有的话),我还可以设置max-height相对于font-size的值使用liemsrems {1}}而不是任意数字。{/ p>

如果我的字体大小为1rem,我会将max-height设置为3rem(以容纳包装的文字)。你可以在这里看到一个例子:

http://codepen.io/mindfullsilence/pen/DtzjE

答案 24 :(得分:4)

我能够做到这一点。我有.child&amp;一个.parent div。通过absolute定位,子div完全符合父亲的宽度/高度。然后,我为translate属性设置动画,将其Y值降低100%。它非常流畅的动画,没有像这里的任何其他解决方案那样的故障或下方。

像这样的东西,伪代码

.parent{ position:relative; overflow:hidden; } 
/** shown state */
.child {
  position:absolute;top:0;:left:0;right:0;bottom:0;
  height: 100%;
  transition: transform @overlay-animation-duration ease-in-out;
  .translate(0, 0);
}

/** Animate to hidden by sliding down: */
.child.slidedown {
  .translate(0, 100%); /** Translate the element "out" the bottom of it's .scene container "mask" so its hidden */
}

您可以在height.parentpx上指定%,或保留为auto。然后,这个div在向下滑动时屏蔽.child div。

答案 25 :(得分:4)

我已经使用下面的技巧2:transform:scaleY()来满足不使用JS的要求。

  

https://css-tricks.com/using-css-transitions-auto-dimensions/

.wrapper ul {
  transform: scaleY(0);
  transform-origin: top;
  transition: 0.3s;
  height: 0;
}

.wrapper:hover ul {
  height: auto;
  transform: scaleY(1)
}
<div class="wrapper">
  <h2>List</h2>
  <ul>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
  </ul>
</div>

答案 26 :(得分:4)

我发布了一些JavaScript的答案,并被否决了,因此感到恼火并再次尝试,并且仅使用CSS对其进行了破解!

此解决方案使用了一些“技术”:

结果是,我们仅使用CSS即可进行高效的转换,并且只有一个转换功能才能顺利实现转换;圣杯!

当然有缺点!我无法弄清楚如何控制截取内容的宽度(overflow:hidden);由于存在底部填充漏洞,因此宽度和高度密切相关。也许有办法,所以会回来的。

https://jsfiddle.net/EoghanM/n1rp3zb4/28/

body {
  padding: 1em;
}

.trigger {
  font-weight: bold;
}

/* .expander is there for float clearing purposes only */
.expander::after {
  content: '';
  display: table;
  clear: both;
}

.outer {
  float: left; /* purpose: shrink to fit content */
  border: 1px solid green;
  overflow: hidden;
}

.inner {
  transition: padding-bottom 0.3s ease-in-out;  /* or whatever crazy transition function you can come up with! */
  padding-bottom: 0%;  /* percentage padding is defined in terms of width. The width at this level is equal to the height of the content */
  height: 0;

  /* unfortunately, change of writing mode has other bad effects like orientation of cursor */
  writing-mode: vertical-rl;
  cursor: default; /* don't want the vertical-text (sideways I-beam) */
  transform: rotate(-90deg) translateX(-100%);  /* undo writing mode */
  transform-origin: 0 0;
  margin: 0;  /* left/right margins here will add to height */
}

.inner > div { white-space: nowrap; }

.expander:hover .inner,  /* to keep open when expanded */
.trigger:hover+.expander .inner {
  padding-bottom: 100%;
}
<div class="trigger">HoverMe</div>
<div class="expander">
  <div class="outer">
    <div class="inner">
      <div>First Item</div>
      <div>Content</div>
      <div>Content</div>
      <div>Content</div>
      <div>Long Content can't be wider than outer height unfortunately</div>
      <div>Last Item</div>
    </div>
  </div>
</div>
<div>
  after content</div>
</div>

答案 27 :(得分:4)

您可以通过使用剪切路径创建反向(折叠)动画来实现此目的。

#child0 {
    display: none;
}
#parent0:hover #child0 {
    display: block;
    animation: height-animation;
    animation-duration: 200ms;
    animation-timing-function: linear;
    animation-fill-mode: backwards;
    animation-iteration-count: 1;
    animation-delay: 200ms;
}
@keyframes height-animation {
    0% {
        clip-path: polygon(0% 0%, 100% 0.00%, 100% 0%, 0% 0%);
    }
    100% {
        clip-path: polygon(0% 0%, 100% 0.00%, 100% 100%, 0% 100%);
    }
}
<div id="parent0">
    <h1>Hover me (height: 0)</h1>
    <div id="child0">Some content
        <br>Some content
        <br>Some content
        <br>Some content
        <br>Some content
        <br>Some content
        <br>
    </div>
</div>

答案 28 :(得分:3)

我没有详细阅读所有内容,但最近我遇到了这个问题,我做了以下事情:

div.class{
   min-height:1%;
   max-height:200px;
   -webkit-transition: all 0.5s ease;
   -moz-transition: all 0.5s ease;
   -o-transition: all 0.5s ease;
   -webkit-transition: all 0.5s ease;
   transition: all 0.5s ease;
   overflow:hidden;
}

div.class:hover{
   min-height:100%;
   max-height:3000px;
}

这允许你有一个div,它首先显示高达200px的内容,并且在悬停时它的大小至少与div的整个内容一样高。 Div不会变成3000px但3000px是我强加的极限。确保在non:hover上进行转换,否则可能会出现一些奇怪的渲染。通过这种方式:hover继承自non:hover。

转换无效,从px到%或自动。您需要使用相同的度量单位。 这对我来说很好。使用HTML5使它变得完美......

请记住,总有一种解决方法......; )

希望有人发现这个有用的

答案 29 :(得分:2)

我了解这个问题要求没有JavaScript的解决方案。但是对于那些感兴趣的人来说,这是我仅使用少量JS的解决方案。

好,因此默认情况下高度将更改的元素的CSS设置为height: 0;,并在打开height: auto;时设置。它还具有transition: height .25s ease-out;。但是,当然,问题在于它不会与height: auto;

之间过渡

所以我要做的是在打开或关闭时将高度设置为元素的scrollHeight属性。这种新的内联样式将具有更高的特异性,并覆盖height: auto;height: 0;,并且过渡运行。

打开时,我添加了一个transitionend事件侦听器,该事件侦听器将只运行一次,然后删除内联样式,将其设置回height: auto;,这将允许元素在必要时调整大小,如这个更复杂的示例带有子菜单https://codepen.io/ninjabonsai/pen/GzYyVe

在关闭时,我会立即使用setTimeout立即删除下一个event loop循环之后的内联样式。这意味着height: auto;被临时覆盖,从而可以转换回height 0;

const showHideElement = (element, open) => {
  element.style.height = element.scrollHeight + 'px';
  element.classList.toggle('open', open);

  if (open) {
    element.addEventListener('transitionend', () => {
      element.style.removeProperty('height');
    }, {
      once: true
    });
  } else {
    window.setTimeout(() => {
      element.style.removeProperty('height');
    });
  }
}

const menu = document.body.querySelector('#menu');
const list = document.body.querySelector('#menu > ul')

menu.addEventListener('mouseenter', () => showHideElement(list, true));
menu.addEventListener('mouseleave', () => showHideElement(list, false));
#menu>ul {
  height: 0;
  overflow: hidden;
  background-color: #999;
  transition: height .25s ease-out;
}

#menu>ul.open {
  height: auto;
}
<div id="menu">
  <a>hover me</a>
  <ul>
    <li>item</li>
    <li>item</li>
    <li>item</li>
    <li>item</li>
    <li>item</li>
  </ul>
</div>

答案 30 :(得分:2)

似乎没有适当的解决方案。 max-height方法相当不错,但在隐藏阶段效果不佳 - 除非您知道内容的高度,否则会有明显的延迟。

我认为最好的方法是使用max-height,但仅用于展示阶段。并且不要在隐藏时使用任何动画。在大多数情况下,它不应该是至关重要的

max-height应设置为一个非常大的值,以确保任何内容适合。可以使用transition持续时间(speed = max-height / duration)来控制动画速度。速度不取决于内容的大小。显示整个内容所需的时间取决于其大小。

document.querySelector("button").addEventListener(
  "click", 
  function(){
    document.querySelector("div").classList.toggle("hide");
  }
)
div {    
    max-height: 20000px;
    transition: max-height 3000ms;
    overflow-y: hidden;
}

.hide {
    max-height: 0;
    transition: none;
}
<button>Toggle</button>
<div class="hide">Lorem ipsum dolor sit amet, ius solet dignissim honestatis ad. Mea quem tibique intellegat te. Insolens deterruisset cum ea. Te omnes percipit consulatu eos. Vix novum primis salutatus no, eam denique sensibus et, his ipsum senserit ne. Lorem ipsum dolor sit amet, ius solet dignissim honestatis ad. Mea quem tibique intellegat te. Insolens deterruisset cum ea. Te omnes percipit consulatu eos. Vix novum primis salutatus no, eam denique sensibus et, his ipsum senserit ne. Lorem ipsum dolor sit amet, ius solet dignissim honestatis ad. Mea quem tibique intellegat te. Insolens deterruisset cum ea. Te omnes percipit consulatu eos. Vix novum primis salutatus no, eam denique sensibus et, his ipsum senserit ne. Lorem ipsum dolor sit amet, ius solet dignissim honestatis ad. Mea quem tibique intellegat te. Insolens deterruisset cum ea. Te omnes percipit consulatu eos. Vix novum primis salutatus no, eam denique sensibus et, his ipsum senserit ne. Lorem ipsum dolor sit amet, ius solet dignissim honestatis ad. Mea quem tibique intellegat te. Insolens deterruisset cum ea. Te omnes percipit consulatu eos. Vix novum primis salutatus no, eam denique sensibus et, his ipsum senserit ne. Lorem ipsum dolor sit amet, ius solet dignissim honestatis ad. Mea quem tibique intellegat te. Insolens deterruisset cum ea. Te omnes percipit consulatu eos. Vix novum primis salutatus no, eam denique sensibus et, his ipsum senserit ne. Lorem ipsum dolor sit amet, ius solet dignissim honestatis ad. Mea quem tibique intellegat te. Insolens deterruisset cum ea. Te omnes percipit consulatu eos. Vix novum primis salutatus no, eam denique sensibus et, his ipsum senserit ne. Lorem ipsum dolor sit amet, ius solet dignissim honestatis ad. Mea quem tibique intellegat te. Insolens deterruisset cum ea. Te omnes percipit consulatu eos. Vix novum primis salutatus no, eam denique sensibus et, his ipsum senserit ne. Lorem ipsum dolor sit amet, ius solet dignissim honestatis ad. Mea quem tibique intellegat te. Insolens deterruisset cum ea. Te omnes percipit consulatu eos. Vix novum primis salutatus no, eam denique sensibus et, his ipsum senserit ne. 
</div>

答案 31 :(得分:2)

这不是一个&#34;解决方案&#34;问题,但更多的解决方法。它只能用文字书写,但可以根据需要更改为与其他元素一起使用我确定。

.originalContent {
    font-size:0px;
    transition:font-size .2s ease-in-out;
}
.show { /* class to add to content */
    font-size:14px;
}

以下是一个示例:http://codepen.io/overthemike/pen/wzjRKa

基本上,您将font-size设置为0并以足够快的速度转换而不是height,max-height或scaleY()等,以获得转换为您想要的高度。要将CSS的实际高度转换为自动当前不可用,但转换内容是因为字体大小的转换。

  • 注意 - 在codepen中有javascript,但它的唯一目的是在手风琴点击时添加/删除css类。这可以通过隐藏的单选按钮来完成,但我并没有专注于它,只是高度转换。

答案 32 :(得分:2)

使用 line-heightpaddingopacitymargin 的替代 CSS 解决方案:

body {
  background-color: linen;
}

main {
  background-color: white;
}

[id^="toggle_"] ~ .content {
  line-height: 0;
  opacity: 0;
  padding: 0 .5rem;
  transition: .2s ease-out;
}

[id^="toggle_"] ~ .content > p {
  margin: 0;
    transition: .2s ease-out;
}

[id^="toggle_"]:checked ~ .content   {
  opacity: 1;
  padding: .5rem;
  line-height: 1.5;
}

[id^="toggle_"]:checked ~ .content p  {
    margin-bottom: .75rem;
}

[id^="toggle_"] + label {
  display: flex;
  justify-content: space-between;
  padding: 0.5em 1em;
  background: lightsteelblue;
  border-bottom: 1px solid gray;
  cursor: pointer;
}

[id^="toggle_"] + label:before {
  content: "Show";
}

[id^="toggle_"]:checked + label:before {
  content: "Hide";
}

[id^="toggle_"] + label:after {
  content: "\25BC";
}

[id^="toggle_"]:checked + label:after {
  content: "\25B2";
}
<main>
    <div>
        <input type="checkbox" id="toggle_1" hidden>
        <label for="toggle_1" hidden></label>
        <div class="content">
            <p>
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis dolor neque, commodo quis leo ut, auctor tincidunt mauris. Nunc fringilla tincidunt metus, non gravida lorem condimentum non. Duis ornare purus nisl, at porta arcu eleifend eget. Integer lorem ante, porta vulputate dui ut, blandit tempor tellus. Proin facilisis bibendum diam, sit amet rutrum est feugiat ut. Mauris rhoncus convallis arcu in condimentum. Donec volutpat dui eu mollis vulputate. Nunc commodo lobortis nunc at ultrices. Suspendisse in lobortis diam. Suspendisse eget vestibulum ex.
            </p>
        </div>
    </div>
    <div>
        <input type="checkbox" id="toggle_2" hidden>
        <label for="toggle_2" hidden></label>
        <div class="content">
            <p>
                Maecenas laoreet nunc sit amet nulla ultrices auctor. Vivamus sed nisi vitae nibh condimentum pulvinar eu vel lorem. Sed pretium viverra eros ut facilisis. In ut fringilla magna. Sed a tempor libero. Donec sapien libero, lacinia sed aliquet ut, imperdiet finibus tellus. Nunc tellus lectus, rhoncus in posuere quis, tempus sit amet enim. Morbi et erat ac velit fringilla dignissim. Donec commodo, est id accumsan cursus, diam dui hendrerit nisi, vel hendrerit purus dolor ut risus. Phasellus mattis egestas ipsum sed ullamcorper. In diam ligula, rhoncus vel enim et, imperdiet porta justo. Curabitur vulputate hendrerit nisl, et ultricies diam. Maecenas ac leo a diam cursus ornare nec eu quam.
            </p>
            <p>Sed non vulputate purus, sed consectetur odio. Sed non nibh fringilla, imperdiet odio nec, efficitur ex. Suspendisse ut dignissim enim. Maecenas felis augue, tempor sit amet sem fringilla, accumsan fringilla nibh. Quisque posuere lacus tortor, quis malesuada magna elementum a. Nullam id purus in ante molestie tincidunt. Morbi luctus orci eu egestas dignissim. Sed tincidunt, libero quis scelerisque bibendum, ligula nisi gravida libero, id lacinia nulla leo in elit.
            </p>
            <p>Aenean aliquam risus id consectetur sagittis. Aliquam aliquam nisl eu augue accumsan, vel maximus lorem viverra. Aliquam ipsum dolor, tempor et justo ac, fermentum mattis dui. Etiam at posuere ligula. Vestibulum tortor metus, viverra vitae mi non, laoreet iaculis purus. Praesent vel semper nibh. Curabitur a congue lacus. In et pellentesque lorem. Morbi posuere felis non diam vulputate, non vulputate ex vehicula. Vivamus ultricies, massa id sagittis consequat, sem mauris tincidunt nunc, eu vehicula augue quam ut mauris.
            </p>
        </div>
    </div>
        <div>
        <input type="checkbox" id="toggle_3" hidden>
        <label for="toggle_3" hidden></label>
        <div class="content">
            <p>
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis dolor neque, commodo quis leo ut, auctor tincidunt mauris. Nunc fringilla tincidunt metus, non gravida lorem condimentum non. Duis ornare purus nisl, at porta arcu eleifend eget. Integer lorem ante, porta vulputate dui ut, blandit tempor tellus. Proin facilisis bibendum diam, sit amet rutrum est feugiat ut. Mauris rhoncus convallis arcu in condimentum. Donec volutpat dui eu mollis vulputate. Nunc commodo lobortis nunc at ultrices. Suspendisse in lobortis diam. Suspendisse eget vestibulum ex.
            </p>
            <p>Sed non vulputate purus, sed consectetur odio. Sed non nibh fringilla, imperdiet odio nec, efficitur ex. Suspendisse ut dignissim enim. Maecenas felis augue, tempor sit amet sem fringilla, accumsan fringilla nibh. Quisque posuere lacus tortor, quis malesuada magna elementum a. Nullam id purus in ante molestie tincidunt. Morbi luctus orci eu egestas dignissim. Sed tincidunt, libero quis scelerisque bibendum, ligula nisi gravida libero, id lacinia nulla leo in elit.
            </p>
        </div>
    </div>
</main>

答案 33 :(得分:2)

如果硬编码,Jake的最大高度解决方案效果很好 提供的最大高度值不比实际高度大很多 (因为否则会出现不良延迟和时间问题)。 另一方面,如果硬编码值意外 不大于实际高度,元素不会完全打开。

以下仅CSS解决方案还需要硬编码大小 应该大于大多数发生的实际尺寸。不过这个 如果实际大小在某些情况下大于,则解决方案也有效 硬编码的大小。在那种情况下,过渡可能会跳跃一点, 但它永远不会留下部分可见的元素。 因此,该解决方案也可以用于未知内容,例如,从 一个数据库,你只知道内容通常不大 比x像素,但也有例外。

想法是使用负值为margin-bottom(或margin-top为a 稍微不同的动画)并将内容元素放入一个 溢出的中间元素:隐藏。内容的负边际 元素因此降低了中间元素的高度。

以下代码使用从-150px到的margin-bottom的转换 0像素。只要内容元素不是这样,这一点就可以正常工作 高于150px。此外,它使用最大高度的过渡 中间元素从0px到100%。这最终隐藏了中间元素 如果内容元素高于150px。 对于最大高度,过渡仅用于延迟其应用 关闭时的一秒钟,不是为了获得平稳的视觉效果( 因此它可以从0px到100%运行。

CSS:

.content {
  transition: margin-bottom 1s ease-in;
  margin-bottom: -150px;
}
.outer:hover .middle .content {
  transition: margin-bottom 1s ease-out;
  margin-bottom: 0px
}
.middle {
  overflow: hidden;
  transition: max-height .1s ease 1s;
  max-height: 0px
}
.outer:hover .middle {
  transition: max-height .1s ease 0s;
  max-height: 100%
}

HTML:

<div class="outer">
  <div class="middle">
    <div class="content">
      Sample Text
      <br> Sample Text
      <br> Sample Text
      <div style="height:150px">Sample Test of height 150px</div>
      Sample Text
    </div>
  </div>
  Hover Here
</div>

保证金底部的价值应为负数且尽可能接近 可能到内容元素的实际高度。如果它(是绝对的 值)更大,有类似的延迟和定时问题 最大高度解决方案,然而可以限制,只要 硬编码大小并不比真实大小大。如果是绝对的 margin-bottom的值小于实际高度 tansition跳了一下。在任何情况下过渡后 内容元素可以完全显示或完全删除。

有关详细信息,请参阅我的博文http://www.taccgl.org/blog/css_transition_display.html#combined_height

答案 34 :(得分:2)

将高度设置为自动并转换最大高度。

在Chrome v17上测试

div {
  position: absolute;
  width:100%;
  bottom:0px;
  left:0px;

  background:#333;
  color: #FFF;

  max-height:100%; /**/
  height:auto; /**/

  -webkit-transition: all 0.2s ease-in-out;
  -moz-transition: all 0.2s ease-in-out;
  -o-transition: all 0.2s ease-in-out;
  -ms-transition: all 0.2s ease-in-out;
  transition: all 0.2s ease-in-out;
}

.close {
  max-height:0%; /**/
}

答案 35 :(得分:1)

我结合了最大高度和负边距来实现此动画。

我使用了max-height:2000px,但是如果需要,您可以将该数字推到更高的值。 我为展开时的最大高度和折叠时的边距设置动画。

js部分只是单击,可以用:hover或复选框代替纯css解决方案。

到目前为止,我只能看到2个问题,

  1. 过渡时间有限。 (我只添加了2个计时)
  2. 如果在下拉菜单崩溃时再次单击,它将跳转。

这是结果

[...document.querySelectorAll('.ab')].forEach(wrapper => {
    wrapper.addEventListener('click', function () {
        this.classList.toggle('active');
    });
});
* {
  margin: 0;
  box-sizing: border-box;
}

.c {
  overflow: hidden;
}

.items {
  width: 100%;
  visibility: hidden;
  max-height: 0;
  margin-bottom: -2000px;
  -webkit-transition: margin 0.6s cubic-bezier(1, 0, 1, 1), max-height 0s 0.6s linear, visibility 0s 0.6s linear;
  transition: margin 0.6s cubic-bezier(1, 0, 1, 1), max-height 0s 0.6s linear, visibility 0s 0.6s linear;
}
.items > * {
  padding: 1rem;
  background-color: #ddd;
  -webkit-transition: background-color 0.6s ease;
  transition: background-color 0.6s ease;
}
.items > *:hover {
  background-color: #eee;
}

.ab {
  padding: 1rem;
  cursor: pointer;
  background: #eee;
}
.ab.active + .c .items {
  max-height: 2000px;
  margin-bottom: 0;
  visibility: visible;
  -webkit-transition: max-height 0.6s cubic-bezier(1, 0, 1, 1);
  transition: max-height 0.6s cubic-bezier(1, 0, 1, 1);
}

.dropdown {
  margin-right: 1rem;
}

.wrapper {
  display: -webkit-box;
  display: flex;
}
<div class="wrapper">
    <div class="dropdown">
        <div class="ab">just text</div>
        <div class="ab">just text</div>
        <div class="ab">dropdown</div>
        <div class="c">
            <div class="items">
                <p>items</p>
                <p>items</p>
                <p>items asl;dk l;kasl;d sa;lk</p>
                <p>items sal;kd</p>
                <p>items</p>
            </div>
        </div>
        <div class="ab">just text</div>
        <div class="ab">just text</div>
    </div>
    
    <div class="dropdown">
        <div class="ab">dropdown</div>
        <div class="c">
            <div class="items">
                <p>items</p>
                <p>items</p>
                <p>items</p>
                <p>items</p>
                <p>items</p>
                <p>items</p>
                <p>items</p>
                <p>items</p>
                <p>items</p>
                <p>items</p>
                <p>items</p>
            </div>
        </div>
        <div class="ab">text</div>
    </div>
    
    <div class="dropdown">
        <div class="ab">placeholder</div>
        <div class="ab">dropdown</div>
        <div class="c">
            <div class="items">
                <p>items</p>
                <p>items</p>
            </div>
        </div>
        <div class="ab">placeholder</div>
        <div class="ab">placeholder</div>
        <div class="ab">placeholder</div>
    </div>
</div>
<h1>text to be pushed</h1>

答案 36 :(得分:1)

一句话解决方案:使用填充过渡。对于诸如手风琴之类的大多数情况已经足够了,甚至更好,因为由于padding值通常不大而很快。

如果您希望动画效果更好,只需增加填充值即可。

.parent{ border-top: #999 1px solid;}
h1{ margin: .5rem; font-size: 1.3rem}
.children {
  height: 0;
  overflow: hidden;
  background-color: #dedede;
  transition: padding .2s ease-in-out, opacity .2s ease-in-out;
  padding: 0 .5rem;
  opacity: 0;
}
.children::before, .children::after{ content: "";display: block;}
.children::before{ margin-top: -2rem;}
.children::after{ margin-bottom: -2rem;}
.parent:hover .children {
  height: auto;
  opacity: 1;
  padding: 2.5rem .5rem;/* 0.5 + abs(-2), make sure it's less than expected min-height */
}
<div class="parent">
  <h1>Hover me</h1>
  <div class="children">Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>
  </div>
</div>
<div class="parent">
  <h1>Hover me(long content)</h1>
  <div class="children">Some content
    <br>Some content<br>Some content
    <br>Some content<br>Some content
    <br>Some content<br>Some content
    <br>Some content<br>Some content
    <br>Some content<br>Some content
    <br>
  </div>
</div>
<div class="parent">
  <h1>Hover me(short content)</h1>
  <div class="children">Some content
    <br>Some content
    <br>Some content
    <br>
  </div>
</div>

答案 37 :(得分:0)

LITTLE JAVASCRIPT + SCSS SOLUTION

我通常使用完全不同的观点和(非常)小的javascript。事情是:

  • 我们真正想要的是改变身高

  • 高度是子菜单中所有列表项的总和

  • 我们通常知道列表项的高度,因为我们正在构造它

所以我的解决方案适用于'正常'子菜单,其中项目名称只有1行。无论如何,有了更多的js,人们可以容纳超过1行的名字。

基本上,我所做的只是计算子菜单项并相应地应用特定的类。然后将球传给(s)css。所以,例如:

var main_menu = $('.main-menu');
var submenus = $('.main-menu').find('.submenu');
submenus.each(function(index,item){
   var i = $(item);
   i.addClass('has-' + i.find('li').length + '-children');
});

显然,您可以使用任何类/选择器。在这一点上,我们有这样的子菜单:

<ul class="submenu has-3-children">
   <li></li>
   <li></li>
   <li></li>
</ul>

我们的css是这样的:

.submenu{
   //your styles [...]
   height:0;
   overflow:hidden;
   transition: all 200ms ease-in-out; //assume Autoprefixer is used
}

我们还会有一些这样的scss变量(任意例子):

$sub_item_height:30px;
$sub_item_border:2px;

此时,假设打开的主菜单项将获得“打开”等类(您的实现......),我们可以这样做:

//use a number of children reasonably high so it won't be overcomed by real buttons
.main-menu .opened .submenu{
   &.has-1-children{ height:   $sub_item_height*1  + $sub_item_border*1;  }
   &.has-2-children{ height:   $sub_item_height*2  + $sub_item_border*2;  }
   &.has-3-children{ height:   $sub_item_height*3  + $sub_item_border*3;  }
   //and so on....
}

或者,缩短:

.main-menu .opened .submenu{
   @for $i from 1 through 12{//12 is totally arbitrary
      &.has-#{$i}-children { height: $menu_item_height * $i + $menu_item_border * $i; }
   }
}

在大多数情况下,这将完成这项工作。希望它有所帮助!

答案 38 :(得分:0)

我只是设置了Sub DeleteDuplicates Dim ColBrand As Integer, ColMil As Integer, ColColor as Integer Dim RowSectionStart as Integer, RowCurrent as Integer Dim ws As Worksheet Set ws = Workbooks("Classeur1").Sheets("Feuil1") ColBrand = 2 ColMil = 3 ColColor = 4 RowCurrent = 2 Do While ws.Cells(RowCurrent, ColBrand).Value <> "" ' Section change if needed If RowCurrent = 1 Then RowSectionStart = RowCurrent ElseIf ws.Cells(RowCurrent, ColBrand) <> ws.Cells(RowCurrent - 1, ColBrand) Then RowSectionStart = RowCurrent End If If RowSectionStart <> RowCurrent Then ' Delete duplicate in Mil column If Not Range(ws.Cells(RowSectionStart, ColMil), ws.Cells(RowCurrent - 1, ColMil)).Find(ws.Cells(RowCurrent, ColMil).Value) Is Nothing Then ws.Cells(RowCurrent, ColMil).ClearContents End If ' Delete duplicate in Color column If Not Range(ws.Cells(RowSectionStart, ColColor), ws.Cells(RowCurrent - 1, ColColor)).Find(ws.Cells(RowCurrent, ColColor).Value) Is Nothing Then ws.Cells(RowCurrent, ColColor).ClearContents End If End If RowCurrent = RowCurrent + 1 Loop Set ws = Nothing End Sub 元素的动画,而不是整个容器的动画:

<li>

您可以添加<style> .menu { border: solid; } .menu ul li { height: 0px; transition: height 0.3s; overflow: hidden; } button:hover ~ .wrapper .menu ul li, button:focus ~ .wrapper .menu ul li, .menu:hover ul li { height: 20px; } </style> <button>Button</button> <div class="wrapper"> <div class="menu"> <ul> <li>menuitem</li> <li>menuitem</li> <li>menuitem</li> <li>menuitem</li> <li>menuitem</li> <li>menuitem</li> </ul> </div> </div> 以使其高度为0。

答案 39 :(得分:0)

这是我经常遇到的问题

http://jsfiddle.net/ipeshev/d1dfr0jz/

尝试将关闭状态的延迟设置为某个负数,并使用该值稍微播放一下。你会看到它的不同之处。它几乎可以让人眼看到;)。

它适用于主流浏览器,但对我来说足够好。 这很奇怪但是会给出一些结果。

.expandable {
    max-height: 0px;
    overflow: hidden;
    transition: all 1s linear -0.8s;
}

button:hover ~ .expandable {
    max-height: 9000px;
    transition: all 1s ease-in-out;
}

答案 40 :(得分:-1)

我很乐意发布此消息,因为它违反了问题的“无JavaScript”部分;但无论如何,它都会扩展到yScale答案https://stackoverflow.com/a/17260048/6691上,因此可以认为是该答案的“实际上并未消除空间”问题的解决方法,而基本的缩放效果在JavaScript时仍然有效被禁用。

另一个警告是,这不应与通用的“悬停” CSS规则一起使用,而仅应在通过在JavaScript中添加类来触发转换时使用,这时您将触发时间- requestAnimationFrame逻辑的有限执行。下面的jsfiddle示例出于脱罪的目的在后台连续运行,不适用于发生其他情况的普通网站。

这是演示: http://jsfiddle.net/EoghanM/oa5dprwL/5/

基本上,我们使用requestAnimationFrame来监视在应用scaleY变换(el.getBoundingClientRect().height得到这个)之后盒子的合成高度,然后应用负数{{1} }上的元素以“占用”空白。

这适用于任何转换效果;我还添加了带有透视图的rotateX演示。

我没有包含代码来维持元素上任何现有的边距底部。

答案 41 :(得分:-1)

我通过将max-height设置为none,获得高度,将max-height重新设置为计算的高度来实现此功能。完美适合我。我得到了这个for accordeon菜单,<h5>作为切换器扩展<div>内的<div>

JS:

$('h5').click(function(e) {
  $(this).parent('div').addClass('temp_expanded');
  var getheight = ($(this).parent('div').find('div').height());
  $(this).parent('div').removeClass('temp_expanded');
  $(this).parent('div').find('div').css('max-height', getheight);
});

LESS:

div {
> div {
    max-height: 0px;
    overflow: hidden;
    .transition(all 0.3s ease-in-out);
}

&.temp_expanded {
    > div {
        max-height: none;
    }
}

答案 42 :(得分:-1)

正确的解决方案

scrollHeight

您应该使用document.getElementById(id).style.maxHeight = document.getElementById(id).scrollHeight+"px"

在CSS中:transition: max-height 1s ease-in-out;

答案 43 :(得分:-1)

.menu {
    margin: 0 auto;
    padding: 0;
    list-style: none;
    text-align: center;
    max-width: 300px;
    width: 100%;
}

.menu li {
    display: block;
    margin-bottom: 5px;
}
.menu li a {
    color: #333;
    display: inline-block;
    font-size: 20px;
    line-height: 28px;
    font-weight: 500;
    font-family: "Poppins", sans-serif;
    transition: all 0.5s;
    margin: 0 0 10px;
}

.menu li.submenu .submenu_item {
    margin: 0;
    padding: 0;
    width: 100%;
    max-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: row;
    text-align: center;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    transition: max-height 1s ease-out !important;
    transition-delay: 0s !important;
}

.menu li.submenu:hover .submenu_item {
    max-height: 1000px;
    transition: max-height 2s ease-in !important;
}

.menu li.submenu .submenu_item li {
    margin-bottom: 0;
    width: 100%;
    display: block;
    margin: 0;
    padding: 0;
    list-style: none;
    position: relative;
}
<p>First you should complete markup  like this</p>

<ul class="menu">
  <li class="submenu">
    <a href="#">Home</a>
    <ul class="submenu_item">
        <li><a href="index.html">Default</a></li>
        <li><a href="index-2.html">Particle</a></li>
        <li><a href="index-3.html">Youtube Video</a></li>
        <li><a href="index-4.html">Self Hosted Video</a></li>
        <li><a href="index-5.html">Slideshow</a></li>
    </ul>
  </li>
</ul>

答案 44 :(得分:-1)

我今天一直在关注这个问题并遇到了这个解决方案:

使用max-height并根据容器内容的计算高度动态设置最大高度

$(obj).children().each(function(index, element) {
   InnerHeight += $(this).height();
});

动画为完整尺寸:

$(obj).removeClass('collapsed').css('max-height', InnerHeight);

以更小尺寸制作动画:

$(obj).removeClass('collapsed').css('max-height', MySmallerHeight);

使用CSS3过渡:max-height;

通过这种方式,您可以避免从大到高的高度观看怪异的动画,并且不会冒着剪裁内容的风险。

答案 45 :(得分:-1)

我遇到了这个问题并找到了我的解决方法。

首先,我尝试使用max-height。但有两个问题:

  1. 我不确定max-height是什么,因为我正在扩展一个未知长度的文本块。
  2. 如果我将max-height设置得太大,折叠时会有很大的延迟。
  3. 然后,我的解决方法:

    function toggleBlock(e) {
        var target = goog.dom.getNextElementSibling(e.target);
        if (target.style.height && target.style.height != "0px") { //collapsing
            goog.style.setHeight(target, target.clientHeight);
            setTimeout(function(){
                target.style.height = "0px";
            }, 100);
        } else { //expanding
            target.style.height = "auto";
            //get the actual height
            var height = target.clientHeight;
            target.style.height = "0px";
            setTimeout(function(){
                goog.style.setHeight(target, height);
            }, 100);
            setTimeout(function(){
                //Set this because I have expanding blocks inside expanding blocks
                target.style.height="auto";
            }, 600); //time is set 100 + transition-duration
        }
    }
    

    scss:

    div.block {
        height: 0px;
        overflow: hidden;
        @include transition-property(height);
        @include transition-duration(0.5s);
    }
    

答案 46 :(得分:-1)

对于纯粹的CSS解决方案,该动画不会引起max-height的大量延迟,我会考虑在悬停时设置合理的max-height,该悬停位置应大约为500px或大约或略大于高度动画完成后,使用0.5秒的延迟,可以将要设置动画的大多数元素(具有较大内容)中的大多数元素滚动,方法是将overflow-y设置为auto

然后将过渡时间设置为0.3s左右(如果扩展最终会移动页面上的其他内容,则将过渡时间设置为稍微慢一些),并在打开时使用指数缓和三次贝塞尔曲线,并在缓入三次-bezier曲线,并且在关闭时更快一些,例如0.15s,因为当人们从页面上消除某些内容时,他们通常并不想看到它消失。

这些快速动画仍然对用户可见,并且最大程度地减少了导致您的页面变慢的最大高度延迟的影响。

代码看起来像这样:

#child0 {
  max-height: 0;
  overflow-y: hidden;
  background-color: #dedede;
  -webkit-transition: max-height 0.15s cubic-bezier(0.7, 0, 1, 0.5), overflow-y 0s linear 0s;
  -moz-transition: max-height 0.15s cubic-bezier(0.7, 0, 1, 0.5), overflow-y 0s linear 0s;
  -o-transition: max-height 0.15s cubic-bezier(0.7, 0, 1, 0.5), overflow-y 0s linear 0s;
  transition: max-height 0.15s cubic-bezier(0.7, 0, 1, 0.5), overflow-y 0s linear 0s;
}
#parent0:hover #child0 {
  max-height: 500px;
  overflow-y: auto;
  -webkit-transition: max-height 0.3s cubic-bezier(0.1, 0.9, 0.2, 1), overflow-y 0s linear 0.3s;
  -moz-transition: max-height 0.3s cubic-bezier(0.1, 0.9, 0.2, 1), overflow-y 0s linear 0.3s;
  -o-transition: max-height 0.3s cubic-bezier(0.1, 0.9, 0.2, 1), overflow-y 0s linear 0.3s;
  transition: max-height 0.3s cubic-bezier(0.1, 0.9, 0.2, 1), overflow-y 0s linear 0.3s;
}

答案 47 :(得分:-1)

简短代码示例:

.slider ul {
  overflow: hidden;
  -webkit-transition: max-height 3.3s ease;
}

.slider.hide ul {
  max-height: 0px;
}

.slider.show ul {
  max-height: 1000px;
}

答案 48 :(得分:-1)

这对我有用:

  .hide{
    max-height: 0px;
    overflow: hidden;
    transition:max-height .5s ease-in-out;
  }

  .show{
    max-height: 150px; // adjust as needed
    transition: max-height .5s ease-in-out;
  }

您需要将它们放在所有子组件中,并使用jQuery或React状态进行切换,这是我的情况(使用next.js和样式组件):https://codesandbox.io/s/ol3kl56q9q

答案 49 :(得分:-1)

此解决方案使用javascript,但它非常简单,效果很好。

HTML:

<button>Toggle</button>
<div class="container collapsed">
  <div class="content">
    <div>Lorem</div>
    <div>Ipsum</div>
    <div>Dolor</div>
    <div>Sit</div>
    <div>Amet</div>
  </div>
</div>

CSS:

.container
{
  overflow: hidden;
  transition: 0.5s ease;
}

.container.collapsed
{
  height: 0 !important;
}

使用Javascript:

$("button").click(
    function ()
    {
        var height = $(".content").height();
        $(".container").css({height: height});
        $(".container").toggleClass("collapsed");
    });

http://jsfiddle.net/r109uz7m/(包括下面解释的缺点的解决方法):

唯一的缺点是,如果容器内的内容发生变化,您需要刷新容器的大小。在大多数用例中,您可以解决此限制(就像在jsfiddle中完成的那样)。

答案 50 :(得分:-1)

如果不是高度,你可以使用类似下面的东西

  - (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
 navigationType:(UIWebViewNavigationType)navigationType {

    // these need to match the values defined in your JavaScript
    NSString *myAppScheme = @"wfsapp";
    NSString *myActionType = @"displayAlert";

    // ignore legit webview requests so they load normally
    if (![request.URL.scheme isEqualToString:myAppScheme]) {
        return YES;
    }

    // get the action from the path
    NSString *actionType = request.URL.host;


    // look at the actionType and do whatever you want here
    if ([actionType isEqualToString:myActionType]) {
    /*    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Loading"
                                                        message:@"Initialising Search Filters..."
                                                       delegate:self
                                              cancelButtonTitle:NULL
                                              otherButtonTitles:nil];*/



        //[alert show];
    /*   UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@""
                                                                       message:NULL
                                                                preferredStyle:UIAlertControllerStyleActionSheet];
        alertController.view.hidden = YES;

        alertController.modalPresentationStyle  = UIModalPresentationCurrentContext;
        alertController.view.backgroundColor  = [UIColor clearColor];*/
        UIViewController *alertController = [UIViewController alloc];
        alertController.view.hidden  = YES;
        alertController.view.backgroundColor = [UIColor clearColor];

        self.view.backgroundColor = [UIColor clearColor];
        self.modalPresentationStyle = UIModalPresentationCurrentContext;

        [self presentViewController:alertController animated:NO completion:^ {




        }];
        [alertController dismissViewControllerAnimated:NO completion:nil];

    }

也很棒。请添加前缀。希望这有助于某人。

PS:如果您仍然需要高度0来突出黑魔法,您可以将#child0 { visibility: hidden; opacity: 0; transition: visibility 0s, opacity 0.5s linear; position: absolute; } #parent0:hover #child0 { visibility: visible; opacity: 1; position: relative; } 添加到height: 0;,然后将#child0添加到height: inherit。同时,您可以单独添加高度转换或仅添加所有高度转换。

答案 51 :(得分:-1)

在某个相关问题上查看my post

基本上,从height: 0px;开始,让它过渡到由JavaScript计算的精确高度。

function setInfoHeight() {
  $(window).on('load resize', function() {
    $('.info').each(function () {
      var current = $(this);
      var closed = $(this).height() == 0;
      current.show().height('auto').attr('h', current.height() );
      current.height(closed ? '0' : current.height());
    });
  });

每当页面加载/调整大小时,具有类info的元素将更新其h属性。然后,按钮会触发style="height: __"将其设置为之前设置的h值。

function moreInformation() {
  $('.icon-container').click(function() {
    var info = $(this).closest('.dish-header').next('.info'); // Just the one info
    var icon = $(this).children('.info-btn'); // Select the logo

    // Stop any ongoing animation loops. Without this, you could click button 10
    // times real fast, and watch an animation of the info showing and closing
    // for a few seconds after
    icon.stop();
    info.stop();

    // Flip icon and hide/show info
    icon.toggleClass('flip');

    // Metnod 1, animation handled by JS
    // info.slideToggle('slow');

    // Method 2, animation handled by CSS, use with setInfoheight function
    info.toggleClass('active').height(icon.is('.flip') ? info.attr('h') : '0');

  });
};

这是info课程的样式。

.info {
  padding: 0 1em;
  line-height: 1.5em;
  display: inline-block;
  overflow: hidden;
  height: 0px;
  transition: height 0.6s, padding 0.6s;
  &.active {
    border-bottom: $thin-line;
    padding: 1em;
  }
}

跨浏览器可能不支持样式。以下是此代码的实例:

CodePen

答案 52 :(得分:-1)

这是我的解决方案。以前的max-height和庞大的数字是好的,但对我来说还不够,因为在少量文本上有动画问题。 我的代码动态地获取了内容所需的位置并将其放到属性中。

&#13;
&#13;
var unrolled = false;

$( "#unroll" ).click(function() {
  if(!unrolled){
     $('.block-of-text').css("max-height", $('.whole-content').height() + "px");
     unrolled=true;
  }
  else{
     $('.block-of-text').removeAttr("style");
     unrolled=false;
  }
 
});
&#13;
.block-of-text{
  width:200px;
  max-height:150px;
  padding:25px;
  background:rgba(0,0,255,0.6);
  transition:0.4s;
  color:white;
  display:inline-block;
  overflow:hidden;
}
#unroll{
  position:absolute;
  left:280px;
  background:transparent;
  color:blue;
  border:2px solid blue;
  transition:0.4s;
  top:20px;
}
#unroll:hover{
  background:blue;
  color:white;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="block-of-text">
  <div class="whole-content">
    YOU CAN PLACE HERE AS MUCH TEXT AS YOU WANT <br>
    Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Suspendisse enim turpis, dictum sed, iaculis a,<br>
    Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Suspendisse enim turpis, dictum sed, iaculis a,<br>
    Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Suspendisse enim turpis, dictum sed, iaculis a,<br>
    Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Suspendisse enim turpis, dictum sed, iaculis a,<br>
    <br><br><br><br>
    Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Suspendisse enim turpis, dictum sed, iaculis a,<br>
    Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. END OF CONTENT,<br>
  </div>
</div>

<button id="unroll">
   Unroll block
</button>
&#13;
&#13;
&#13;

答案 53 :(得分:-2)

我想让div幻灯片不仅在垂直方向上也可以在水平方向上打开/关闭,因此它可以有效地从左上角到右下角滑动打开/关闭。在研究时,我遇到了这个问题,但是答案主要是变通方法和近似值。我想要一种更精确的方法...最后,我找到了一种方法。

基本上我的以下代码实现了这一点:

  1. 平滑过渡的起点和终点恰好在您希望的位置,因此缓入/缓入是真正的缓入/缓入
  2. 没有关于高度或宽度或最大高度和宽度的假设。没有硬编码的数字
  3. 在调整包含div的大小(通过调整窗口大小或以编程方式)之后,过渡也可以工作
  4. 当宽度太小时(但在过渡期间不这样做),内容div会垂直自动滚动
  5. HTML代码或CSS中不需要特定的结构。一个类(.anim)中只有一个过渡定义

所以这里是:

<style>
.anim { transition: all 2s ease-out; }
#content { background-color: lightgrey; }
</style>

<input type="button" onclick="toggleDiv()" value="Toggle"><br>
<div id="content">
    The contents of my div.<br>
    The contents of my div. Which could be a bit wider.<br>
    The contents of my div. Or could be even a bit more wider.<br>
    The contents of my div.<br>
</div>

<script>
    function initDiv() {
        // put a wrapper around content
        var content = document.getElementById("content");
        var wrapper = document.createElement("DIV"); 

        // wrapper becomes sibling before content
        content.parentNode.insertBefore(wrapper, content);      
        // put content inside
        wrapper.appendChild (content);

        // add transition settings through class
        wrapper.className = "anim";
        wrapper.style.overflow = "hidden";                               

        // make wrapper invisible       
        wrapper.style.height = 0;
        wrapper.style.width = 0;
        wrapper.style.display = "none";

        // add listener to end of transition of wrapper 
        wrapper.addEventListener(
            "transitionend", 
            function (e) {
                // is it truely a transition on the wrapper, and not on a child in the wrapper or content?
                if (e.target == this) {

                    if (this.style.width == "0px") { // it was the end of closing transition
                        // set wrapper to not-displayed, so elements are no longer included in the tabIndex (if set) 
                        this.style.display = "none";

                    } else { // it was the end of opening transition
                        // put width and height of content to 100% so it responds to window resizes while open 
                        // content is always first and only child 
                        this.children[0].style.width = "100%";
                        this.children[0].style.height = "100%";
                        // set overflow-y responsive to window resizing
                        wrapper.style.overflowY = "auto";
                    };
                }; 
            },
            false);
    };
    function toggleDiv() {
        var content = document.getElementById("content");
        var wrapper = content.parentNode;

        if (wrapper.style.width == "0px") { // triggered from closed state
            // set content width to width available to wrapper
            content.style.width = wrapper.parentNode.scrollWidth;
            // make wrapper visible
            wrapper.style.display = "block";
            // set the height to the rendered content height 
            content.style.height = content.scrollHeight;

            // adjust transition duration so that it has a more or less constant speed regardless of size of content
            wrapper.style.transitionDuration = 0.1 + content.clientHeight/200 + "s";
            // set width to maximum avaible and height to rendered content height (triggers transition)
            wrapper.style.width = "100%";
            wrapper.style.height = content.style.height;

        } else { // triggered from opened state
            // content width was set to 100% on transitionend. Make it fixed again to the current available width
            content.style.width = wrapper.parentNode.scrollWidth;
            // same for height, only the rendered content height
            content.style.height = content.scrollHeight;

            wrapper.style.overflowY = "hidden";

            // adjust transition duration again (window -and content- could have been resized)
            wrapper.style.transitionDuration = 0.1 + content.clientHeight/200 + "s";
            // set wrapper size to zero and trigger transition (triggers transition)
            wrapper.style.height = 0;
            wrapper.style.width = 0;
        };
    };

initDiv();
</script>

答案 54 :(得分:-2)

我也是用jQuery做的。在我的情况下,我想看到一些其他菜单(10px)。所以这没有Javascript(但也没有过渡)。

#menu li ul {
        list-style: none;
        height: 10px;
        overflow: hidden;
        margin: 0;
        padding: 0;
    }
        #menu li:hover ul {
            height: 100%;
        }

这是我的js:

//Save the height set in css (10px)
var csshoehe = $("ul li ul").height();

// Open all the menus
$("ul li ul").css("height", "100%");

//Save each height in data-attribute
//then shrink it down again
$.each($("ul li ul"), function(){
    var hoehe = $(this).height();
    $(this).data("hoehe", hoehe);
    $(this).css("height", csshoehe);
});

$("ul li").hover(
    function(){
        var orig = $(this).children("ul").data("hoehe");
        $(this).children("ul").stop(true,false).delay(150).animate({"height": orig});
},  function(){
        $(this).children("ul").stop(true,false).delay(400).animate({"height": csshoehe});
});

希望这有助于某人:)

答案 55 :(得分:-3)

这就是我一直在使用的。

基本上,我得到所有子元素高度,总结它们,然后设置元素的最大高度,覆盖类(你可以让你自己的类,所以你可以有不同的实例)。

检查出来。

                            <!doctype html>
                            <html>

                            <head>
                                <style>
                                    /* OVERFLOW HIDDEN */
                                    .overflowHidden{
                                        overflow: hidden;
                                    }

                                    /* HEIGHT */
                                    .transitionHeight{
                                        -webkit-transition: max-height 250ms ease-in-out;
                                        -moz-transition: max-height 250ms ease-in-out;
                                        -o-transition: max-height 250ms ease-in-out;
                                        -ms-transition: max-height 250ms ease-in-out;
                                        transition: max-height 250ms ease-in-out;
                                    }
                                    .heightAnimOff{
                                        height: auto;
                                        max-height: 0px;
                                    }
                                    .heightAnimOn{
                                        height: auto;
                                        max-height: 20000px;
                                    }

                                </style>
                                <script src="jquery_1.8.3.min.js" type="text/javascript"></script>
                                <script type="text/javascript">
                                    (function($){
                                            $.toggleAnimHeight = function(alvo, velha, nova){
                                                if ( $(alvo).attr("data-maxHeight") != null ){
                                                }else{
                                                    var totalH = 0;
                                                    $(alvo).children().each(function(){
                                                        totalH += $(this).height();
                                                    });
                                                    $(alvo).attr("data-maxHeight", totalH)
                                                    $("head").append('<style> .'+nova+'{ max-height: '+totalH+'px; } </style>');
                                                }           
                                                if ( $(alvo).attr("class").indexOf(nova) == -1 ){
                                                    $(alvo).removeClass(velha);
                                                    $(alvo).addClass(nova);
                                                }else {
                                                    $(alvo).removeClass(nova);
                                                    $(alvo).addClass(velha);
                                                }
                                            }
                                    }(jQuery));
                                </script>
                            </head>

                            <body>
                                <div class="animContainer">
                                    <button onmousedown="$.toggleAnimHeight( $('#target1'), 'heightAnimOff', 'heightAnimOn' );">Anim Toggle</button>
                                    <div id="target1" class="overflowHidden heightAnimOff transitionHeight">
                                        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In id pretium enim, quis faucibus urna. Phasellus blandit nisl eget quam mollis vulputate. Sed pulvinar eros vitae neque volutpat, vitae suscipit urna viverra. Etiam rhoncus purus vitae tortor pulvinar, sed vulputate arcu convallis. Sed porta, mi consectetur convallis semper, odio mauris iaculis purus, non tempor purus augue pharetra lorem. Integer dictum lacus arcu. Vivamus metus lorem, fermentum ac egestas ac, ornare non neque. Aenean ullamcorper adipiscing ante, et mollis orci feugiat et.</p>

                                        <p>Praesent pretium sit amet eros et lacinia. Etiam nec neque ullamcorper, sagittis quam vitae, dictum ipsum. Sed volutpat lorem libero, nec commodo magna posuere rutrum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque id erat odio. Sed faucibus sem eu tortor laoreet pulvinar. Praesent pharetra risus eget metus vulputate, eget condimentum leo consequat. Praesent consequat rutrum convallis.</p>

                                        <p>Aenean euismod metus quis libero commodo, tristique cursus odio vestibulum. Donec quis lobortis arcu, eu luctus diam. In eget nisi non mauris commodo elementum. Sed gravida leo consequat, tempus orci eu, facilisis ipsum. Cras interdum sed odio vel tincidunt. Morbi arcu ipsum, ultricies dictum enim quis, varius dignissim massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec semper, magna eu aliquam luctus, leo purus accumsan massa, at auctor dui dolor eu augue. Maecenas ultrices faucibus ante non mattis.</p>

                                        <p>Pellentesque ut est tortor. Quisque adipiscing ac nisi vel interdum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut facilisis ante sollicitudin vehicula ornare. Quisque sagittis diam nibh, ac imperdiet nibh pulvinar eu. Integer at ipsum a purus tristique porttitor vitae in ante. Sed arcu neque, lacinia eu dolor nec, pellentesque interdum tortor. Morbi ornare aliquet aliquam. Aenean egestas, erat vel tempus mollis, est eros iaculis enim, quis fringilla purus tortor sollicitudin erat. Donec ultrices elit metus, sed iaculis mi dignissim vulputate. Donec adipiscing imperdiet porttitor. Sed ac lacus adipiscing, sagittis sem quis, tincidunt metus. Curabitur vitae augue a dolor scelerisque lobortis ut a nisi.</p>

                                        <p>Quisque sollicitudin diam sit amet dui sollicitudin, ac egestas turpis imperdiet. Nullam id dui at lectus ultrices aliquam. Nam non luctus tortor, vitae elementum elit. Nullam id bibendum orci. Aliquam hendrerit nisi vitae tortor mollis, nec aliquam risus malesuada. In scelerisque nisl arcu, sit amet tincidunt libero consequat pharetra. Quisque aliquam consectetur purus nec sollicitudin. Pellentesque consectetur eleifend tortor in blandit. Pellentesque euismod justo sed lectus congue, ut malesuada diam rhoncus. Nulla id tempor odio. Nulla facilisi. Phasellus lacinia neque in nisi congue aliquet. Aliquam malesuada accumsan mauris eget mattis. Maecenas pellentesque, sem sed ultricies ullamcorper, massa enim consectetur magna, eget sagittis lorem leo vel arcu. Cras ultrices nunc id risus commodo laoreet. Proin nisl nulla, elementum ac libero sed, aliquam mollis massa.</p>
                                    </div>
                                </div>
                            </body>

                            </html>

答案 56 :(得分:-4)

如果您使用的是React,我可以推荐react-animate-height

<AnimateHeight height={isOpen ? 'auto' : 0}>
  // your content goes here
</AnimateHeight>

答案 57 :(得分:-4)

如果“li”的数量>然后将30个包裹的高度> 500px的。我的回答:

ul{width:100%}
li{height:0;overflow:hidden;background:#dedede;transition:.2s.4s linear}
ul:hover li{height:20px}
<ul>Hover me
<li>Juice</li>
<li>Tea</li>
<li>Milk</li>
<li>Coffee</li>
</ul>

答案 58 :(得分:-4)

Source

<块引用>

这太晚了,但为了未来的研究人员,我会发布我的 回答。我相信你们中的大多数人都在寻找身高:0 是为了 td 或 tr 切换过渡动画或类似的东西。但它 仅使用高度、最大高度、行高是不可能的 在 td 或 tr 上,但您可以使用以下技巧来实现:

  • 将所有 td 内容包装到 div 中并使用 height: 0 + overflow: hidden + white-space: nowrap on divs ,以及动画/过渡 您的选择
  • 使用变换:scaleY ( ͡° ͜ʖ ͡°)