高さを移行するにはどうすればよいですか:0; 高さまで:自動; CSSを使用していますか?

2250
Hailwood 2010-08-18 16:50.

<ul>CSSトランジションを使用してスライドダウンを作成しようとしています。

はで<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>

30 answers

2919
jake 2011-12-01 08:42.

max-heightトランジションで使用しheightます。ではありません。そしてmax-height、あなたの箱がこれまでに得るよりも大きな何かに値を設定してください。

こちらの別の回答で、ChrisJordanが提供するJSFiddleデモを参照してください。

#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>

345
dotnetCarpenter 2013-06-24 00:57.

代わりにscaleYを使用する必要があります。

ul {
  background-color: #eee;
  transform: scaleY(0);    
  transform-origin: top;
  transition: transform 0.26s ease;
}
p:hover ~ ul {
  transform: scaleY(1);
}
<p>Hover This</p>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

jsfiddleで上記のコードのベンダープレフィックスバージョンを作成し、高さの代わりにscaleYを使用するようにjsfiddleを変更しました。

214
robertc 2010-08-19 02:46.

現在、関連する高さの1つがである場合、高さをアニメーション化することはできませんauto。2つの明示的な高さを設定する必要があります。

128
Steven Vachon 2015-05-30 04:05.

私がいつも使っていた解決策は、最初にフェードアウトしてからfont-sizepaddingとのmargin値を縮小することでした。ワイプと同じようには見えませんが、スタティックheightまたはがなくても機能しますmax-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>

98
balpha 2017-05-15 04:33.

これがこの質問に対する30の答えであることを私は知っていますが、それは価値があると思うので、ここに行きます。これは、次のプロパティを持つCSSのみのソリューションです。

  • 最初は遅れがなく、移行が早く止まることはありません。両方向(拡張と折りたたみ)で、CSSで300ミリ秒の遷移期間を指定すると、遷移には300ミリ秒の期間がかかります。
  • (とは異なりtransform: scaleY(0))実際の高さを遷移するため、折りたたみ可能な要素の後にコンテンツがある場合は正しい処理を行います。
  • (他の解決策のように)魔法数がありますが(「ボックスがこれまでにない長さを選ぶ」など)、仮定が間違っていても致命的ではありません。移行は、その場合には驚くほど見ていないかもしれませんが、移行前と後に、これは問題ではありません:拡大(でheight: autoあなたが選ぶ場合)状態、全体の内容が常に正しい高さ(とは異なり、例えばを持っているmax-heightことが判明したことを低すぎる)。そして、折りたたまれた状態では、高さはゼロです。

デモ

これは、すべて同じCSSを使用する、高さが異なる3つの折りたたみ可能な要素を含むデモです。「スニペットの実行」をクリックした後、「フルページ」をクリックすることをお勧めします。JavaScriptはcollapsedCSSクラスを切り替えるだけであり、測定は含まれないことに注意してください。(チェックボックスまたはを使用すると、JavaScriptをまったく使用せずにこの正確なデモを実行できます:target)。また、移行を担当するCSSの部分はかなり短く、HTMLには追加のラッパー要素が1つだけ必要であることに注意してください。

$(function () { $(".toggler").click(function () {
    $(this).next().toggleClass("collapsed"); $(this).toggleClass("toggled"); // this just rotates the expander arrow
  });
});
.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;
}
<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>

それはどのように機能しますか?

実際、これを実現するには2つの移行が必要です。それらの1つはmargin-bottom、0px(展開された状態)から-2000px折りたたまれた状態(この回答と同様)に遷移します。ここでの2000は最初の魔法の数であり、ボックスがこれより高くならないという仮定に基づいています(2000ピクセルは妥当な選択のようです)。

margin-bottomトランジションを単独で使用することには、2つの問題があります。

  • 実際に2000ピクセルを超えるボックスがある場合、margin-bottom: -2000pxすべてが非表示になるわけではありません。折りたたまれた場合でも、目に見えるものが表示されます。これは、後で行うマイナーな修正です。
  • 実際のボックスの高さが1000ピクセルで、トランジションの長さが300ミリ秒の場合、表示されるトランジションは約150ミリ秒後にすでに終了しています(または、反対方向に150ミリ秒遅れて開始します)。

この2番目の問題の修正は、2番目の遷移が発生する場所であり、この遷移は概念的にラッパーの最小の高さを対象としています(実際にmin-heightはこのプロパティを使用していないため、「概念的に」。これについては後で詳しく説明します)。

これは、両方とも同じ期間の下部マージン遷移と最小高さ遷移を組み合わせることで、同じ期間の全高からゼロ高への遷移を組み合わせた方法を示すアニメーションです。

左側のバーは、負の下部マージンが下部を上に押し上げ、表示される高さを減らす方法を示しています。真ん中のバーは、最小の高さによって、折りたたみの場合は遷移が早く終了せず、展開の場合は遷移が遅く開始されないようにする方法を示しています。右側のバーは、2つの組み合わせにより、ボックスが正しい時間内に全高からゼロ高にどのように遷移するかを示しています。

私のデモでは、高さの上限値として50pxを選択しました。これは2番目の魔法の数であり、ボックスの高さよりも低くする必要があります。50pxも妥当なようです。そもそも高さが50ピクセルでもない要素を折りたたみ可能にしたいと思うことはほとんどないようです。

アニメーションでわかるように、結果の遷移は連続的ですが、区別できません。最小の高さが下マージンで調整された完全な高さに等しい瞬間に、速度が突然変化します。これは、両方の遷移に線形タイミング関数を使用し、遷移全体が非常に遅いため、アニメーションで非常に目立ちます。実際の場合(上部のデモ)、遷移には300ミリ秒しかかからず、下部マージンの遷移は線形ではありません。私は両方のトランジションでさまざまなタイミング関数を試してみましたが、最終的には、さまざまなケースで最適に機能するように感じました。

修正すべき2つの問題が残っています。

  1. 高さが2000ピクセルを超えるボックスが折りたたまれた状態で完全に隠されていない、上からのポイント。
  2. 逆の問題。非表示でない場合、トランジションが実行されていないときでも、高さが50ピクセル未満のボックスは、最小の高さが50ピクセルに保たれるため、高すぎます。

最初の問題を解決するにはmax-height: 0、折りたたまれた場合にコンテナ要素に0s 0.3s遷移を指定します。これは、実際には遷移ではないがmax-height、遅延して適用されることを意味します。移行が終了した場合にのみ適用されます。これが正しく機能するmax-heightためには、反対の、折りたたまれていない状態の数値も選択する必要があります。ただし、2000pxの場合とは異なり、大きすぎる数値を選択すると遷移の品質に影響します。この場合、それは実際には問題ではありません。したがって、高さがこれに近づくことはないことがわかっているほど高い数値を選択することができます。私は百万ピクセルを選びました。100万ピクセルを超える高さのコンテンツをサポートする必要があると思われる場合は、1)申し訳ありませんが、2)ゼロをいくつか追加してください。

2番目の問題はmin-height、最小の高さの遷移に実際に使用していない理由です。代わり::afterに、コンテナ内にheight50pxからゼロに遷移する疑似要素があります。これには、min-height:と同じ効果があります。疑似要素が現在持っている高さよりもコンテナが縮小することはありません。ただしheight、ではなくmin-heightを使用max-heightしているため、遷移が終了したら、(もう一度遅延を使用して)疑似要素の実際の高さをゼロに設定し、少なくとも遷移の外側で、小さな要素でも正しい高さ。のでmin-heightある強いよりもmax-height、我々は、コンテナの使用している場合、これは動作しませんmin-height代わりに擬似要素ののをheight。同じようにmax-height、前の段落では、これはmax-heightまた、移行の反対側の端の値を必要とします。ただし、この場合は50pxを選択できます。

Chrome(Win、Mac、Android、iOS)、Firefox(Win、Mac、Android)、Edge、IE11(デバッグに煩わされなかったデモのフレックスボックスレイアウトの問題を除く)、Safari(Mac、iOS)でテスト済み)。フレックスボックスと言えば、フレックスボックスを使用せずにこれを機能させることができるはずです。実際、CSSトランジションがないという事実を除いて、IE7でほとんどすべてを機能させることができると思います。これは、かなり無意味な演習になります。

86
jhurshman 2010-07-01 03:32.

少しの非セマンティックなジゲリーポケリーでできます。私の通常のアプローチは、コンテンツの高さの測定にのみ使用されるスタイルのない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の高さをautoに設定し、それをアニメーション化したいのですが、それは機能していないようです(高さは設定されますが、アニメーションは発生しません)。

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

51
Catharsis 2011-06-27 09:05.

CSS3トランジションを使用して高さをアニメーション化する視覚的な回避策は、代わりにパディングをアニメーション化することです。

完全なワイプ効果は得られませんが、transition-durationとpaddingの値を試してみると、十分に近づくはずです。高さ/最大高さを明示的に設定したくない場合は、これが探しているものになります。

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/ (jsFiddleの上のstephbandをリフオフ)

46
Adam 2012-03-19 14:44.

私の回避策は、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>

46
Oleg Vaskevich 2014-10-21 12:57.

受け入れられた答えはほとんどの場合機能しますdivが、高さが大幅に異なる場合はうまく機能しません。アニメーションの速度はコンテンツの実際の高さに依存せず、途切れ途切れに見える可能性があります。

CSSを使用して実際のアニメーションを実行することはできますが、を使用する代わりに、JavaScriptを使用してアイテムの高さを計算する必要がありますauto。jQueryは必要ありませんが、互換性が必要な場合はこれを少し変更する必要があるかもしれません(Chromeの最新バージョンで動作します:))。

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';
    }
}
#menu #list {
    height: 0px;
    transition: height 0.3s ease;
    background: #d5d5d5;
    overflow: hidden;
}
<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>

33
amn 2016-07-06 08:59.

Element.prototype.scrollHeightここで役立つ可能性があり、純粋なCSSトランジションで使用できるプロパティについてはほとんど言及されていませんが、スクリプトのサポートが明らかに必要になります。プロパティには、折りたたまれた高さの結果としてコンテンツがオーバーフローするかどうか、およびどのようにオーバーフローするかに関係なく、要素の「完全な」高さが常に含まれます(例height: 0)。

そのため、height: 0(事実上完全に折りたたまれた)要素の場合、その「通常の」または「完全な」高さは、そのscrollHeight値(常にピクセル長)を通じて容易に利用できます。

このような要素の場合、たとえば(ul元の質問に従って使用して)次のように遷移がすでに設定されていると仮定します。

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

CSSのみを使用して、次のような高さのアニメーション化された「拡張」をトリガーできます(ここではul変数がリストを参照していると仮定しています)。

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

それでおしまい。リストを折りたたむ必要がある場合は、次の2つのステートメントのいずれかを実行します。

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

私の特定のユースケースは、未知の、そしてしばしばかなりの長さのリストをアニメーション化することを中心に展開したので、任意の「十分な大きさ」heightまたはmax-height仕様に落ち着き、カットオフコンテンツまたは突然スクロールする必要があるコンテンツを危険にさらすことに抵抗がありました(overflow: autoたとえば) 。さらに、max-height使用される高さがに達するよりもはるかに早く最大値に達する可能性があるため、イージングとタイミングはベースのソリューションでは壊れmax-heightています9999px。そして、画面の解像度が上がるにつれて、ピクセルの長さ9999pxは私の口に悪い味を残します。私の意見では、この特定の解決策はエレガントな方法で問題を解決します。

最後に、CSSの将来の改訂では、作成者がこれらの種類のことをさらにエレガントに行う必要があることを期待しています。「計算済み」と「使用済み」および「解決済み」の値の概念を再検討し、遷移を計算済みに適用する必要があるかどうかを検討してください。widthおよびを使用した遷移を含む値height(現在、少し特別な扱いを受けています)。

30
malihu 2014-12-17 13:35.

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/

30
Vivek Maharajh 2016-02-27 07:19.

ハードコードされた値はありません。

JavaScriptはありません。

概算はありません。

秘訣は、非表示と複製を使用divして、ブラウザに100%の意味を理解させることです。

この方法は、アニメーション化する要素のDOMを複製できる場合に適しています。

.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%;
}
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>

21
Andrew Messier 2016-10-17 06:55.

私がこれを投稿するとき、すでに30以上の回答がありますが、私の回答は、ジェイクによってすでに受け入れられている回答よりも改善されていると感じています。

max-height多くのコメント投稿者が指摘しているように、max-height値を実際の高さに非常に近く設定する必要があるため、CSS3トランジションを使用するだけで発生する問題に満足していませんでした。そうしないと、遅延が発生します。その問題の例については、このJSFiddleを参照してください。

これを回避するために(JavaScriptを使用せずに)、transform: translateYCSS値を遷移させる別のHTML要素を追加しました。

これは、max-heighttranslateYが使用されることを意味しmax-heightます。要素がその下の要素を押し下げることを可能にし、必要なtranslateY「インスタント」効果を提供します。の問題はmax-heightまだ存在しますが、その影響は少なくなります。これは、max-height値にはるかに大きな高さを設定でき、心配が少なくなることを意味します。

全体的な利点は、元に戻る(折りたたみ)ときに、ユーザーにtranslateYアニメーションがすぐに表示されるため、どれだけ時間がmax-heightかかるかは問題ではないことです。

フィドルとしての解決策

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>

18
VIDesignz 2015-08-02 12:35.

わかりました。とても簡単な答えを思いついたと思います...いいえmax-heightrelativeポジショニングを使用し、li要素を処理し、純粋なCSSです。私はFirefox以外ではテストしていませんが、CSSで判断すると、すべてのブラウザーで動作するはずです。

フィドル: 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>
15
Sijav 2013-10-07 00:34.

編集:更新された回答
をスクロールダウンしてドロップダウンリストを作成し、この投稿を見ました...多くの異なる回答がありますが、ドロップダウンリストも共有することにしました...完璧ではありませんが、少なくともcssのみを使用します落ちる!私はtransform:translateY(y)を使用して、リストをビューに変換してきました...
テストで詳細を確認できます
http://jsfiddle.net/BVEpc/4/
ドロップダウンリストが上から来ているので、すべてのliの後ろにdivを配置しました。これが必要だったことを正しく表示するには、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;
}

移行後の2回目は遅延であり、ドロップダウンリストがアニメーションで閉じられた後に非表示になります...
後で誰かがこのリストの恩恵を受けることを願っています。

編集:私はpplが実際にこのプロトタイプを使用しているとは信じられません!このドロップダウンメニューは1つのサブメニュー専用で、それだけです!! IE 8をサポートして、ltr方向とrtl方向の両方に2つのサブメニューを持つことができるより良いものを更新しました。
Fiddle for LTR
Fiddle for RTL
うまくいけば、誰かがこれが将来役立つと思うでしょう。

11
Stuart Badminton 2011-04-11 01:36.

min-heightとmax-heightも指定すれば、height:0からheight:autoに移行できます。

div.stretchy{
    transition: 1s linear;
}

div.stretchy.hidden{
    height: 0;
}

div.stretchy.visible{
    height: auto;
    min-height:40px;
    max-height:400px;
}
9
Lee Comstock 2017-08-05 11:01.

Flexboxソリューション

長所:

  • シンプル
  • JSなし
  • スムーズな移行

短所:

  • 要素は固定高さのフレックスコンテナに入れる必要があります

それが機能する方法は、常にflex-basisを使用することです。つまり、コンテンツを含む要素でautoを実行し、代わりにflex-growとflex-shrinkを遷移します。

編集:XboxOneインターフェースに触発された改良されたJSフィドル。

* {
  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フィドル

7
jamie 2013-07-10 06:14.

@jakeの答えを拡張すると、トランジションは最大の高さの値まで完全に進み、非常に高速なアニメーションが発生します。:hoverとoffの両方にトランジションを設定すると、クレイジーな速度をもう少し制御できます。

したがって、li:hoverは、マウスが状態に入るときであり、ホバーされていないプロパティの遷移は、マウスを離れることになります。

うまくいけば、これはいくつかの助けになるでしょう。

例えば:

.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/

6
csuwldcat 2013-10-10 12:35.

ノードごとのハードセットコードや初期化するユーザーコードを必要とせずに、0を含む任意の開始高さから自動(フルサイズで柔軟)に移行する方法は次のとおりです。 https://github.com/csuwildcat/transition-auto。これは基本的にあなたが望むものの聖杯だと私は信じています->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ファイルをページにドロップします-すべてJustWorks™

/ *高さのコード:自動; 移行中* /

(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);
6
JonTroncoso 2015-05-19 21:25.

私は本当に固溶体を思いついたと思います

OK!私はこの問題がインターネットと同じくらい古いことを知っていますが、私はミュータントトランジションと呼ばれるプラグインに変えた解決策があると思います。私のソリューションはstyle=""、DOMに変更があるたびに、追跡される要素の属性を設定します。その結果、トランジションに優れたole CSSを使用でき、ハッキーな修正や特別なjavascriptを使用できなくなります。あなたがしなければならない唯一のことはあなたが問題の要素で追跡したいものを使用して設定することですdata-mutant-attributes="X"

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

それでおしまい!このソリューションは、MutationObserverを使用してDOMの変更を追跡します。このため、実際に何かを設定したり、JavaScriptを使用して手動でアニメーションを作成したりする必要はありません。変更は自動的に追跡されます。ただし、MutationObserverを使用しているため、これはIE11 +でのみ移行します。

フィドル!

  • からheight: autoへの移行のデモンストレーションheight: 100%
  • Demonstrating transitioning height: auto when adding children
6
pbatey 2013-08-17 15:46.

Jake's answer to animate the max-height is great, but I found the delay caused by setting a large max-height annoying.

One could move the collapsable content into an inner div and calculate the max height by getting the height of the inner div (via JQuery it'd be the 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');
});

Here's a jsfiddle link: http://jsfiddle.net/pbatey/duZpT

Here's a jsfiddle with the absolute minimal amount of code required: http://jsfiddle.net/8ncjjxh8/

5
Charley 2011-05-27 15:13.

I realize this thread is getting old, but it ranks high on certain Google searches so I figure it's worth updating.

You also just get/set the element's own height:

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

You should dump this Javascript immediately after target_box's closing tag in an inline script tag.

5
Josh Ribakoff 2014-03-14 13:19.

I was able to do this. I have a .child & a .parent div. The child div fits perfectly within the parent's width/height with absolute positioning. I then animate the translate property to push it's Y value down 100%. Its very smooth animation, no glitches or down sides like any other solution here.

Something like this, pseudo code

.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 */
}

You would specify a height on .parent, in px, %, or leave as auto. This div then masks out the .child div when it slides down.

5
EoghanM 2019-11-09 08:10.

I posted an answer with some JavaScript and got downvoted, so got annoyed and tried again, and have cracked it with CSS only!

This solution uses a few 'techniques':

  • padding-bottom:100% 'hack' where percentages are defined in terms of the current width of the element. More info on this technique.
  • float shrink-wrapping, (necessitating an extra div to apply the float clearing hack)
  • unsemantic use of https://caniuse.com/#feat=css-writing-mode and some transformations to undo it (this allows use of the padding hack above in a vertical context)

The upshot though is that we get performant transitioning using CSS only, and a single transition function to smoothly achieve the transition; the holy grail!

Of course, there's a downside! I can't work out how to control the width at which content gets cut off (overflow:hidden); because of the padding-bottom hack, the width and height are intimately related. There may be a way though, so will come back to it.

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>

4
HandiworkNYC.com 2011-11-03 13:58.

Here's a solution I just used in combination with jQuery. This works for the following HTML structure:

<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>

and the function:

    $('#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);
    });

You could then use a click function to set and remove the height using 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 }
4
mindfullsilence 2014-05-13 10:00.

I've recently been transitioning the max-height on the li elements rather than the wrapping ul.

The reasoning is that the delay for small max-heights is far less noticeable (if at all) compared to large max-heights, and I can also set my max-height value relative to the font-size of the li rather than some arbitrary huge number by using ems or rems.

If my font size is 1rem, I'll set my max-height to something like 3rem (to accommodate wrapped text). You can see an example here:

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

3
work.stella84 2013-03-07 13:13.

I have not read everything in detail but I have had this problem recently and I did what follows:

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;
}

This allows you to have a div that at first shows content up to 200px height and on hover it's size becomes at least as high as the whole content of the div. The Div does not become 3000px but 3000px is the limit that I am imposing. Make sure to have the transition on the non :hover, otherwise you might get some strange rendering. In this way the :hover inherits from the non :hover.

Transition does not work form px to % or to auto. You need to use same unit of measure. This works fine for me. Using HTML5 makes it perfect....

Remember that there is always a work around... ; )

Hope someone finds this useful

3
Helmut Emmelmann 2014-08-08 23:24.

The max-height solution from Jake works well, if the hard-coded max-height value supplied is not much bigger than the real height (because otherwise there are undesirable delays and timing problems). On the other hand if the hard-coded value accidentially is not bigger than the real height the element won't open up completely.

The following CSS only solution also requires a hard-coded size that should be bigger than most of the occurring real sizes. However this solution also works if the real size is in some situations bigger than the hard-coded size. In that event the transition might jump a bit, but it will never leave a partially visible element. So this solution could also be used for unknown content, e.g. from a database, where you just know that the content is usually not bigger than x pixels, but there are exceptions.

Idea is to use a negative value for margin-bottom (or margin-top for a slightly diffenrent animation) and to place the content element into a middle element with overflow:hidden. The negative margin of the content element so reduces the height of the middle element.

The following code uses a transition on margin-bottom from -150px to 0px. This alone works fine as long as the content element is not higher than 150px. In addition it uses a transition on max-height for the middle element from 0px to 100%. This finally hides the middle element if the content element is higher than 150px. For max-height the transition is just used to delay its application by a second when closing, not for a smooth visiual effect ( and therefore it can run from 0px to 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>

The value for margin bottom should be negative and as close as possible to the real height of the content element. If it('s absoute value) is bigger there are similar delay and timing problems as with the max-height solutions, which however can be limited as long as the hard coded size is not much bigger than the real one. If the absolute value for margin-bottom is smaller than the real height the tansition jumps a bit. In any case after the transition the content element is either fully displayed or fully removed.

For more details see my blog post http://www.taccgl.org/blog/css_transition_display.html#combined_height

3
Andrii Kovalenko 2020-02-24 04:42.

You could do this by creating a reverse (collapse) animation with clip-path.

#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>

2
Mike S. 2016-10-12 14:12.

This isn't exactly a "solution" to the problem, but more of a workaround. It only works as written with text, but can be changed to work with other elements as needed I'm sure.

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

Here is an example: http://codepen.io/overthemike/pen/wzjRKa

Essentially, you set the font-size to 0 and transition that instead of the height, or max-height, or scaleY() etc. at a quick enough pace to get the height to transform to what you want. To transform the actual height with CSS to auto isn't currently possible, but transforming the content within is, hence the font-size transition.

  • Note - there IS javascript in the codepen, but it's only purpose is to add/remove css classes on click for the accordion. This can be done with hidden radio buttons, but I wasn't focused on that, just the height transformation.

Related questions

MORE COOL STUFF

「水曜日」シーズン1の中心には大きなミステリーがあります

「水曜日」シーズン1の中心には大きなミステリーがあります

Netflixの「水曜日」は、典型的な10代のドラマ以上のものであり、実際、シーズン1にはその中心に大きなミステリーがあります.

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ケイト・ミドルトンは、州の夕食会と州の訪問中にカミラ・パーカー・ボウルズからスポットライトを奪いたくなかった、と専門家は言う.

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンが、オリビア・ワイルドが彼女とハリー・スタイルズとの間の「難しい」が「非常に友好的」な分割を恒久的にすることを望んでいる理由を見つけてください.

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする 

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする&nbsp;

エリザベス女王の死後、ケイト・ミドルトンが舞台裏で「非常に困難な時期」を過ごしていたと伝えられている理由を調べてください.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

パンデミックは終わったかもしれないが、Covid-19 は終わっていない

パンデミックは終わったかもしれないが、Covid-19 は終わっていない

2021 年 6 月 8 日にニューヨーク市で開催された covid-19 パンデミックで亡くなった人々の命を偲び、祝うために、ネーミング ザ ロスト メモリアルズが主催するイベントと行進の最中に、グリーンウッド墓地の正門から記念碑がぶら下がっています。週末、ジョー・バイデン大統領は、covid-19 パンデミックの終息を宣言しました。これは、過去 2 年以上にわたり、公の場でそうするための長い列の中で最新のものです。

デビル・イン・オハイオの予告編は、エミリー・デシャネルもオハイオにいることを明らかにしています

デビル・イン・オハイオの予告編は、エミリー・デシャネルもオハイオにいることを明らかにしています

オハイオ州のエミリー・デシャネル みんな早く来て、ボーンズが帰ってきた!まあ、ショーボーンズではなく、彼女を演じた俳優. エミリー・デシャネルに最後に会ってからしばらく経ちました.Emily Deschanel は、長期にわたるプロシージャルな Bones の Temperance “Bones” Brennan としてよく知られています。

ドナルド・トランプはFBIのマー・ア・ラーゴ襲撃映像をリリースする予定ですか?

ドナルド・トランプはFBIのマー・ア・ラーゴ襲撃映像をリリースする予定ですか?

どうやら、ドナルド・トランプに近い人々は、今月初めにFBIによって家宅捜索された彼のMar-a-Lago財産からの映像を公開するよう彼に勧めています. 前大統領はテープを公開するかどうかを確認していませんが、息子はフォックス・ニュースにそうなるだろうと語った.

Andor は、他の Star Wars ショーから大きな距離を置きます。

Andor は、他の Star Wars ショーから大きな距離を置きます。

アンドールの一場面。数十年前、ジョージ・ルーカスがスター・ウォーズのテレビ番組を制作するのを妨げた主な理由は、お金でした。

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、子供向けのパズルの本の序文を書き、ジョージ王子、シャーロット王女、ルイ王子と一緒にテキストを読むと述べた.

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

Yak's Produce は、数十個のつぶれたメロンを野生動物のリハビリ専門家であるレスリー グリーンと彼女のルイジアナ州の救助施設で暮らす 42 匹の動物に寄付しました。

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

8 枚目のスタジオ アルバムのリリースに向けて準備を進めているデミ ロヴァートは、「スーパー グレート ガイ」と付き合っている、と情報筋は PEOPLE に確認しています。

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

イーサン プラスの誕生日のお祝いは、TLC のウェルカム トゥ プラスビルのシーズン 4 のフィナーレで、戦争中の母親のキム プラスと妻のオリビア プラスを結びつけました。

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

ホームオフィスのセットアップ術を極めよう!AppExert の開発者は、家族全員が一緒にいる場合でも、在宅勤務の技術を習得しています。祖父や曽祖父が共同家族で暮らしていた頃の記憶がよみがえりました。

2022 年、私たちのデジタル ライフはどこで終わり、「リアル ライフ」はどこから始まるのでしょうか?

20 年前のタイムトラベラーでさえ、日常生活におけるデジタルおよびインターネットベースのサービスの重要性に驚くことでしょう。MySpace、eBay、Napster などのプラットフォームは、高速化に焦点を合わせた世界がどのようなものになるかを示してくれました。

ニューロマーケティングの秘密科学

ニューロマーケティングの秘密科学

マーケティング担当者が人間の欲望を操作するために使用する、最先端の (気味が悪いと言う人もいます) メソッドを探ります。カートをいっぱいにして 3 桁の領収書を持って店を出る前に、ほんの数点の商品を買いに行ったことはありませんか? あなたは一人じゃない。

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

私たちが住んでいる世界を確実に理解するには、データが必要です。ただし、空間参照がない場合、このデータは地理的コンテキストがないと役に立たなくなる可能性があります。

Language