css3 - CSS从相对于0; 过渡到高度auto ;

  显示原文与译文双语对照的内容

我正在尝试使用CSS转换创建一个 <ul>

ulheight: 0; 处开始。 悬停时,高度设置为 height:auto; 。 然而,这是导致其出现,过渡.

如果我从 height: 40px;height: auto;,那么它会滑向 height: 0;,然后突然跳到正确的高度。

否则我怎么做?


#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>
时间:

在转换中使用 max-height 而不是 height 。 在max-height上设置一个比你的盒子更大的值。

请参见 JSFiddle演示由 Chris Jordan提供的另一个应答列表。


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

当涉及的高度之一是 auto 时,当前不能设置高度动画,必须设置两个显式高度。

你应该使用拨号方式。

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,而不是高度, http://jsfiddle.net/dotnetCarpenter/7cnfc/206/。

你可以用一点点 non-semantic jiggery-pokery 。 我通常的方法是动画一个外部DIV的高度,它有一个单独的子元素,它是一个仅用于测量内容高度的style-less DIV 。


<style type="text/css">
 #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;
 }
</style>
<script type='text/javascript'>
 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";
 }
 }
</script>
<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>

一想就能免除measuringWrapperdiv的高度设置为汽车和动画,但这似乎并没有( 设置了高度,但没有发生动画) 工作。


<style type="text/css">
 #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;
 }
</style>
<script type='text/javascript'>
 function growDiv() {
 var growDiv = document.getElementById('grow');
 if (growDiv.clientHeight) {
 growDiv.style.height = 0;
 } else {
 growDiv.style.height = 'auto';
 }
 }
</script>
<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>

我的解释是动画需要一个明确的高度。 高度( 开始或者结束高度) 为"自动"时,无法在高度上得到动画。

我的解决方案是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>

使用CSS3转换动画高度的视觉解决方法是为填充设置动画效果。

你没有得到完全的擦除效果,但是使用transition-duration和填充值可以让你接近。 如果你不想显式设置高度/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/ ( stephband jsFiddle之上的riffed )

只想链接到演示解决方案/批准的jeff答案的小提琴:

http://jsfiddle.net/thechrisjordan/3Fc7D/23/


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

这是一种从任何高度开始,包括 0、汽车( 全尺寸和灵活) 无需hard-set代码per-node基础上或任何user-code初始化: 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>

下面是要包含在页面中的代码块,后面是 gravy:

高度/* 代码: 自动;转换 */


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

/* 代码演示 */


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

你应该使用自动拨号。

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/

你可以从 height:0 转换为 height:auto,提供min-height和 max-height 。


div.stretchy{
 transition: 1s linear;
}

div.stretchy.hidden{
 height: 0;
}

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

...