我正在尝试使用CSS转换制作一个<ul>幻灯片。

<ul>开始于高度:0;。悬停时,高度设置为height:auto;。然而,这导致它简单地出现,

如果我从高度做:40px;至高度:自动;,那么它将向上滑动到高度:0;,然后突然跳到正确的高度。

如果不使用JavaScript,我怎么能做到这一点?

#子0{高度:0;溢出:隐藏;背景色:#dedede;-moz过渡:高度1s容易;-webkit过渡:高度1s轻松;-o过渡:高度1s容易;过渡:高度1s;}#parent0:悬停#child0{高度:自动;}#孩子40{高度:40px;溢出:隐藏;背景色:#dedede;-moz过渡:高度1s容易;-webkit过渡:高度1s轻松;-o过渡:高度1s容易;过渡:高度1s;}#parent40:悬停#child40{高度:自动;}h1小时{字号:粗体;}两个CSS片段之间的唯一区别是一个高度为0,另一个高度是40。<小时><div id=“parent0”><h1>将我悬停(高度:0)</h1><div id=“child0”>一些内容<br>一些内容<br>一些内容<br>一些内容<br>一些内容<br>一些内容<br></div></div><小时><div id=“parent40”><h1>将我悬停(高度:40)</h1><div id=“child40”>一些内容<br>一些内容<br>一些内容<br>一些内容<br>一些内容<br>一些内容<br></div></div>


当前回答

使用CSS3过渡设置高度动画的一个视觉解决方法是设置填充动画。

你不太能得到完全的擦除效果,但在过渡持续时间和填充值之间进行切换应该会让你足够接近。如果您不想显式设置高度/最大高度,这应该是您想要的。

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上重复)

其他回答

我能够做到这一点。我有一个.child和一个.parent div。子div完全符合父div的宽度/高度,具有绝对定位。然后设置平移属性的动画,将其Y值降低100%。它的动画非常流畅,没有任何问题或缺点,就像这里的任何其他解决方案一样。

类似这样,伪代码

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

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

您可以在.parent上指定一个高度,单位为px,%,或保留为auto。这个div然后在向下滑动时屏蔽掉.child div。

一句话解决方案:使用填充过渡。这对于大多数情况(如手风琴)来说已经足够了,甚至更好,因为填充值通常不大,所以速度很快。

如果希望动画过程更好,只需提高填充值即可。

parent{border top:#999 1px solid;}h1{margin:.5rem;字体大小:1.3rem}.儿童{高度:0;溢出:隐藏;背景色:#dedede;过渡:填充。2s易进易出,不透明度。2s容易进易出;填充:0.5雷姆;不透明度:0;}.childre::之前,.childres::之后{content:“”;显示:块;}.children::在{margin-top:-2rem;}之前.children::在{margin-bottom:-2rem;}之后.父级:悬停.子级{高度:自动;不透明度:1;衬垫:2.5雷姆。5雷姆;/*0.5+abs(-2),确保低于预期最小高度*/}<div class=“parent”><h1>将我悬停</h1><div class=“children”>一些内容<br>一些内容<br>一些内容<br>一些内容<br>一些内容<br>一些内容<br></div></div><div class=“parent”><h1>将我悬停(长内容)</h1><div class=“children”>一些内容<br>部分内容<br>部分内容<br>部分内容<br>部分内容<br>部分内容<br>部分内容<br>部分内容<br>部分内容<br>部分内容<br>部分内容<br></div></div><div class=“parent”><h1>悬停我(简短内容)</h1><div class=“children”>一些内容<br>一些内容<br>一些内容<br></div></div>

要从任何起始高度(包括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文件放到页面中:

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

你可以,用一点非语义的小把戏。我通常的方法是设置外部DIV的高度动画,该外部DIV有一个子级,这是一个仅用于测量内容高度的无样式DIV。

函数growDiv(){var growDiv=文档.getElementById('grow');if(growtDiv.clientHeight){growtDiv.style.height=0;}其他{var wrapper=document.querySelector('.measureingWrapper');growDiv.style.height=wrapper.clientHeight+“px”;}}#成长{-moz过渡:高度.5s;-ms过渡:高度.5s;-o过渡:高度.5s;-webkit过渡:高度.5s;过渡:高度.5s;高度:0;溢出:隐藏;轮廓:1px纯红色;}<input type=“button”onclick=“growDiv()”value=“grow”><div id='grow'><div class='measureingWrapper'><div>我部门的内容。</div><div>我部门的内容。</div><div>我部门的内容。</div><div>我部门的内容。</div><div>我部门的内容。</div><div>我部门的内容。</div></div></div>

人们希望能够省去.metringWrapper,只需将DIV的高度设置为auto并设置动画,但这似乎不起作用(设置了高度,但没有动画发生)。

函数growDiv(){var growDiv=文档.getElementById('grow');if(growtDiv.clientHeight){growtDiv.style.height=0;}其他{growDiv.style.height=“自动”;}}#成长{-moz过渡:高度.5s;-ms过渡:高度.5s;-o过渡:高度.5s;-webkit过渡:高度.5s;过渡:高度.5s;高度:0;溢出:隐藏;轮廓:1px纯红色;}<input type=“button”onclick=“growDiv()”value=“grow”><div id='grow'><div>我部门的内容。</div><div>我部门的内容。</div><div>我部门的内容。</div><div>我部门的内容。</div><div>我部门的内容。</div><div>我部门的内容。</div></div>

我的解释是,动画运行需要明确的高度。当高度(起始高度或结束高度)为自动时,无法获得高度动画。

当其中一个高度为自动时,当前无法在高度上设置动画,必须设置两个显式高度。