Come posso cambiare altezza: 0; ad altezza: auto; usando i CSS?

Sto provando a far scorrere

    verso il basso usando le transizioni CSS.

      inizia height: 0; . Al passaggio del mouse, l’altezza è impostata su height:auto; . Tuttavia, questo sta causando semplicemente apparire, non la transizione,

      Se lo faccio da height: 40px; ad height: auto; , quindi scorrerà fino height: 0; e poi balzare all’improvviso all’altezza corretta.

      In quale altro modo potrei farlo senza usare 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. 

      Hover me (height: 0)

      Some content
      Some content
      Some content
      Some content
      Some content
      Some content

      Hover me (height: 40)

      Some content
      Some content
      Some content
      Some content
      Some content
      Some content

      Usa la max-height nella trasformazione e non l’ height . E imposta un valore sull’altezza max-height qualcosa di più grande che il tuo box non otterrà mai.

      Vedi la demo di JSFiddle fornita da Chris Jordan in un’altra risposta qui.

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

      Dovresti invece usare scaleY.

      HTML:

       

      Here (scaleY(1))

      • Coffee
      • Tea
      • Milk

      CSS:

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

      Ho creato una versione con prefisso del fornitore del suddetto codice su jsfiddle, http://jsfiddle.net/dotnetCarpenter/PhyQc/9/ e ho cambiato il tuo jsfiddle per usare scaleY invece di height, http://jsfiddle.net/dotnetCarpenter/ 7cnfc / 206 / .

      Al momento non è ansible animare in altezza quando una delle altezze coinvolte è auto , è necessario impostare due altezze esplicite.

      La soluzione che ho sempre usato è stata quella di sfumare prima, quindi ridurre i valori di font-size , padding e margin . Non ha lo stesso aspetto di una salvietta, ma funziona senza height statica o 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; } 

      Esempio di lavoro:

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

      Puoi, con un po ‘di follia non semantica. Il mio approccio abituale è quello di animare l’altezza di un DIV esterno che ha un singolo figlio che è un DIV senza stile utilizzato solo per misurare l’altezza del contenuto.

       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; } 
        
      The contents of my div.
      The contents of my div.
      The contents of my div.
      The contents of my div.
      The contents of my div.
      The contents of my div.

      So che questa è la risposta trentacinquesima a questa domanda, ma penso che ne valga la pena, quindi ecco qui. Questa è una soluzione solo CSS con le seguenti proprietà:

      • Non c’è ritardo all’inizio e la transizione non si ferma presto. In entrambe le direzioni (espandibile e collassabile), se si specifica una durata della transizione di 300 ms nel CSS, la transizione richiede 300 ms, punto.
      • Sta cambiando l’altezza effettiva (diversamente dalla transform: scaleY(0) ), quindi fa la cosa giusta se c’è del contenuto dopo l’elemento pieghevole.
      • Mentre (come in altre soluzioni) ci sono numeri magici (come “scegli una lunghezza che è più alta di quanto la tua scatola sarà mai”), non è fatale se la tua ipotesi finisce per essere sbagliata. In questo caso, la transizione potrebbe non sembrare sorprendente, ma prima e dopo la transizione, questo non è un problema: nello stato espanso ( height: auto ), l’intero contenuto ha sempre l’altezza corretta (diversamente, ad esempio, se si seleziona un max-height che risulta essere troppo bassa). E nello stato collassato, l’altezza è zero come dovrebbe.

      dimostrazione

      Ecco una demo con tre elementi collassabili, tutti di altezze diverse, che utilizzano tutti lo stesso CSS. Potresti voler fare clic su “Pagina intera” dopo aver fatto clic su “Esegui snippet”. Tieni presente che JavaScript triggers solo la class CSS collapsed , non è prevista alcuna misurazione. (Si potrebbe fare questa demo esatta senza alcun JavaScript usando una casella di controllo o :target ). Si noti inoltre che la parte del CSS responsabile della transizione è piuttosto breve e che l’HTML richiede solo un elemento wrapper aggiuntivo.

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

      Una soluzione visiva per animare l’altezza usando le transizioni CSS3 è invece di animare il padding.

      Non si ottiene abbastanza l’effetto wipe, ma giocare con i valori di durata di transizione e padding dovrebbe avvicinarti abbastanza. Se non vuoi impostare in modo esplicito altezza / altezza massima, questo dovrebbe essere quello che stai cercando.

       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/ (sfogliato stephband sopra jsFiddle)

      La mia soluzione alternativa è di passare dall’altezza massima all’altezza del contenuto esatto per un’animazione fluida, quindi utilizzare un callback transitionEnd per impostare l’altezza massima su 9999px in modo che il contenuto possa essere ridimensionato liberamente.

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

      Smooth CSS Transitions Between height: 0 and height: auto

      A clever workaround is to use max-height instead of height, 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 max-height: 1000px but the content is only 100px high, the animation will be 10x too fast.

      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.

      This solution is a hybrid of the two - transition to the measured content height, then set it to max-height: 9999px after the transition for fluid content sizing.


      The accepted answer works for most cases, but it doesn’t work well when your div can vary greatly in height — the animation speed is not dependent on the actual height of the content, and it can look choppy.

      You can still perform the actual animation with CSS, but you need to use JavaScript to compute the height of the items, instead of trying to use auto . No jQuery is required, although you may have to modify this a bit if you want compatibility (works in the latest version of 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; } 
        

      Use max-height with different transition easing and delay for each state.

      HTML:

       Hover 
      • One
      • Two
      • Three

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

        See example: http://jsfiddle.net/0hnjehjc/1/

        No hard coded values.

        No JavaScript.

        No approximations.

        The trick is to use a hidden & duplicated div to get the browser to understand what 100% means.

        This method is suitable whenever you’re able to duplicate the DOM of the element you wish to animate.

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

        There was little mention of the Element.scrollHeight property which can be useful here and still may be used with a pure CSS transition. The property always contains the “full” height of an element, regardless of whether and how its content overflows as a result of collapsed height (eg height: 0 ).

        As such, for a height: 0 (effectively fully collapsed) element, its “normal” or “full” height is still readily available through its scrollHeight value (invariably a pixel length).

        For such an element, assuming it already has the transition set up like eg (using ul as per original question):

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

        We can trigger desired animated “expansion” of height, using CSS only, with something like the following (here assuming ul variable refers to the list):

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

        Questo è tutto. If you need to collapse the list, either of the two following statements will do:

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

        My particular use case revolved around animating lists of unknown and often considerable lengths, so I was not comfortable settling on an arbitrary “large enough” height or max-height specification and risking cut-off content or content that you suddenly need to scroll (if overflow: auto , for example). Additionally, the easing and timing is broken with max-height -based solutions, because the used height may reach its maximum value a lot sooner than it would take for max-height to reach 9999px . And as screen resolutions grow, pixel lengths like 9999px leave a bad taste in my mouth. This particular solution solves the problem in an elegant manner, in my opinion.

        Finally, here is hoping that future revisions of CSS address authors’ need to do these kind of things even more elegantly — revisit the notion of “computed” vs “used” and “resolved” values, and consider whether transitions should apply to computed values, including transitions with width and height (which currently get a bit of a special treatment).

        As I post this there are over 30 answers already, but I feel my answer improves on the already accepted answer by jake.

        I was not content with the issue that arises from simply using max-height and CSS3 transitions, since as many commenters noted, you have to set your max-height value very close to the actual height or you’ll get a delay. See this JSFiddle for an example of that problem.

        To get around this (while still using no JavaScript), I added another HTML element that transitions the transform: translateY CSS value.

        This means both max-height and translateY are used: max-height allows the element to push down elements below it, while translateY gives the “instant” effect we want. The issue with max-height still exists, but its effect is lessened. This means you can set a much larger height for your max-height value and worry about it less.

        The overall benefit is that on the transition back in (the collapse), the user sees the translateY animation immediately, so it doesn’t really matter how long the max-height takes.

        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); } 
         
        Toggle!

        Content!

        Content!

        Content!

        Content!

        Toggle!

        Content!

        Content!

        Content!

        Content!

        Ok, so I think I came up with a super simple answer… no max-height , uses relative positioning, works on li elements, & is pure CSS. I have not tested in anything but Firefox, though judging by the CSS, it should work on all browsers.

        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

         
        Some Cool Content

        You can transition from height:0 to height:auto providing that you also provide min-height and max-height.

         div.stretchy{ transition: 1s linear; } div.stretchy.hidden{ height: 0; } div.stretchy.visible{ height: auto; min-height:40px; max-height:400px; } 

        I think I came up with a really solid solution

        OK! I know this problem is as old as the internet but I think I have a solution which I turned into a plugin called mutant-transition . My solution sets the style="" attributes for tracked elements whenever theres a change in the DOM. the end result is that you can use good ole CSS for your transitions and not use hacky fixes or special javascript. The only thing you have to do is set what you want to track on the element in question using data-mutant-attributes="X" .

         
        This is an example with mutant-transition

        Questo è tutto! This solution uses MutationObserver to follow changes in the DOM. Because of this, you don’t really have to set anything up or use javascript to manually animate things. Changes are tracked automatically. However, because it uses MutationObserver, this will only transition in IE11+.

        Fiddles!

        • Demonstrating transitioning from height: auto to height: 100%
        • Demonstrating transitioning height: auto when adding children

        EDIT: Scroll down for updated answer
        I was making a drop down list and saw this Post … many different answers but I decide to share my drop down list too, … It’s not perfect but at least it will using only css for drop down! I’ve been using transform:translateY(y) to transform the list to the view …
        You can see more in the test
        http://fiddle.jshell.net/BVEpc/4/
        I’ve placed div behind every li because my drop down list are coming from up and to show them properly this was needed, my div code is:

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

        and hover is :

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

        and because ul height is set to the content it can get over your body content that’s why I did this for ul:

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

        and hover:

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

        the second time after transition is delay and it will get hidden after my drop down list has been closed animately …
        Hope later someone get benefit of this one.

        EDIT: I just can’t believe ppl actually using this prototype! this drop down menu is only for one sub menu and that’s all!! I’ve updated a better one that can have two sub menu for both ltr and rtl direction with IE 8 support.
        Fiddle for LTR
        Fiddle for RTL
        hopefully someone find this useful in future.

        Here’s a way to transition from any starting height, including 0, to auto (full size and flexible) without requiring hard-set code on a per-node basis or any user-code to initialize: https://github.com/csuwildcat/transition-auto . This is basically the holy grail for what you want, I believe –> http://codepen.io/csuwldcat/pen/kwsdF . Just slap the following JS file into your page, and all you need to do after that is add/remove a single boolean attribute – reveal="" – from the nodes you want to expand and contract.

        Here’s all you need to do as the user, once you include the code block found below the example code:

         /*** Nothing out of the ordinary in your styles ***/  /*** Just add and remove one attribute and transition to/from auto! ***/ 
        I have tons of content and I am 0px in height you can't see me...
        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!...

        Here’s the code block to include in your page, after that, it’s all gravy:

        Drop this JS file in your page – it all Just Works™

        / * Code for height: auto; transitioning * /

         (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); 

        / * Code for 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); 

        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/

        Flexbox Solution

        Professionisti:

        • semplice
        • no JS
        • smooth transition

        Contro:

        • element needs to be put in a fixed height flex container

        The way it works is by always having flex-basis: auto on the element with content, and transitioning flex-grow and flex-shrink instead.

        Edit: Improved JS Fiddle inspired by the Xbox One interface.

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

        Super Metroid Prime Fusion

        Resident Evil 2 Remake

        Yolo The Game

        Final Fantasy 7 Remake + All Additional DLC + Golden Tophat

        DerpVille

        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.

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

          

        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 } 

        Expanding on @jake’s answer, the transition will go all the way to the max height value, causing an extremely fast animation – if you set the transitions for both :hover and off you can then control the crazy speed a little bit more.

        So the li:hover is when the mouse enters the state and then the transition on the non-hovered property will be the mouse leave.

        Hopefully this will be of some help.

        per esempio:

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

        Here’s a fiddle: http://jsfiddle.net/BukwJ/

        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.

        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

        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

        Set the height to auto and transition the max-height.

        Tested on 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%; /**/ } 

        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, eg 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:

         
        Sample Text
        Sample Text
        Sample Text
        Sample Test of height 150px
        Sample Text
        Hover Here

        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

        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 classs on click for the accordion. This can be done with hidden radio buttons, but I wasn’t focused on that, just the height transformation.

        This is regular problem I’ve solved like this

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

        Try to set delay of closed state to some negative number and play a little bit with the value. You will see the difference.It can be made almost to lie the human eye ;).

        It works in major browsers, but good enough for me. It is strange but give some results.

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