我正在尝试使用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>


当前回答

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

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

以及功能:

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

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

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

然后,您可以使用click函数使用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 }

其他回答

您应该改用scaleY。

上一页{背景色:#eee;变换:缩放Y(0);变换原点:顶部;转变:转变0.26s;}p: 悬停~ul{变换:缩放Y(1);}<p>将此悬停</p><ul><li>咖啡</li><li>茶</li><li>牛奶</li></ul>

我在jsfiddle上制作了上述代码的供应商前缀版本,并将jsfiddl更改为使用scaleY而不是height。

编辑有些人不喜欢scaleY如何转换内容。如果这是一个问题,那么我建议使用剪辑。

上一页{剪辑:矩形(自动,自动,0,自动);位置:绝对;边距:-1rem 0;衬垫:.5rem;颜色:白色;背景色:rgba(0、0、0和0.8);过渡特性:剪辑;过渡时间:0.5s;过渡时间函数:立方贝塞尔(0.175、0.885、0.32、1.275);}h3:悬停~ul,h3:活性~ul,ul:悬停{剪辑:矩形(自动,自动,10rem,自动);}<h3>悬停在此处</h3><ul><li>此列表</li><li>被剪裁</li><li>剪辑过渡</li><li>将显示它</li></ul><p>一些文本。。。</p>

要从任何起始高度(包括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);

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

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

在过渡中使用最大高度,而不是高度。并将最大高度的值设置为比您的长方体所能获得的值更大的值。

请参阅Chris Jordan提供的JSFiddle演示。

#菜单#列表{最大高度:0;过渡:最大高度0.15s缓和;溢出:隐藏;背景:#d5d5d5;}#菜单:悬停#列表{最大高度:500px;过渡:最大高度0.25s;}<div id=“menu”><a>悬停我</a><ul id=“list”><!-- 创建一组,或不创建一组li来查看时间。--><li>项目</li><li>项目</li><li>项目</li><li>项目</li><li>项目</li></ul></div>

扩展@jake的答案,过渡将一直到最大高度值,从而产生极快的动画效果-如果您同时设置了悬停和关闭两种过渡,则可以进一步控制疯狂的速度。

因此,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/