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


当前回答

我使用的方法是基于字体大小(使用em作为单位)或至少是影响我们想要动画的框的垂直大小的所有内容。然后,如果有任何东西不是以em为单位(例如1px边框),我会在框关闭时将其设置为0,并将所有子对象设置为*。

动画动画显示的是从0到100的字体大小(%)。什么?父级的已知字体大小。

它工作的规则是,动画框中的所有内容必须:

对所有字体大小和行高使用%将em用于所有垂直方向(如高度、边距和顶部/底部填充等)如果将px用于垂直的内容(例如,边框顶部/底部),则在框关闭时应覆盖该内容(例如:边框顶部:0;边框底部:0;)

在某种程度上,您仍然可以使用像素作为参考单位,只需将包装字体大小设置为100px,例如#page{font-size:100px;},因此如果您希望在内部任何地方使用10px,则可以使用0.1em。

这不是任何人都能写的最漂亮的东西,但嘿,这些浏览器并不能为我们提供任何解决这个问题的漂亮方案。一旦箱子的高度无法预测,我们别无选择,只能弄得有些脏,这是我想到的最不脏的东西。

悬停版本:

https://jsfiddle.net/xpsfkb07/1/

#第页{字体大小:calc((35vw+65vh)/30);/*只是一些响应性设计作为奖励*/}#滑动轴承箱{背景色:#e8e8e8;可见性:隐藏;字号:0;/*从0到100%设置动画*/不透明度:0;/*可选的*/过渡:0.5s;}a#ahover:悬停~#slidebox{可见性:可见;字体大小:100%;/*从0到100%设置动画*/不透明度:1;/*可选的*/}a#ahover:not(:hover)~#slidebox*{边框顶部:0;边框底部:0;/*在这里放置任何以像素为单位的垂直线,在本例中为边框*/}a#按钮{显示:内联flex;对齐项目:居中;对齐内容:中心;位置:相对;宽度:20em;高度:3em;填充:0.5em;边框:2px实心#0080ff;边界半径:0.4em;背景色:#8fbfef;颜色:#404040;框大小调整:边框框;}#某种形式的{页边距:1em;边距底部:1em;填充:1 m 4 m 1 m 4 mm;背景色:#d8ffd8;边框:1px实心#888888;}#某种形式的输入{显示:内联块;框大小调整:边框框;字体大小:125%;填充:0.5em;宽度:50%;/*任何水平的都可以是px或%*/边界半径:0.4em;边框:1px纯红色;}<div id=page><a id=ahover href=“#”>悬停我</a><br>下面是滑动框:<div id=slidebox>我是幻灯片框的内容(第1行)<br>我是幻灯片框的内容(第2行)<br><a id=button href=“#”>我是幻灯片框中的某个按钮</a><br>我是幻灯片框的内容(第3行)<br>我是幻灯片框的内容(第4行)。<div id=someform>一个有表格的盒子<br><输入类型=文本值=“文本框”></div>我是幻灯片框的内容(第5行)<br>我是幻灯片框的内容(第6行)。</div>这是在盒子后面。</div>

类别更改版本:

https://jsfiddle.net/8xzsrfh6/

const switch_ele=文档.getElementById('aclass');switch_ele.addEventListener('click',函数(){const box_ele=文档.getElementById('slidebox');box_ele.className=box_ele_className=='显示'?'hide':'显示';},true);#第页{字体大小:calc((35vw+65vh)/30);/*只是一些响应性设计作为奖励*/}#滑动轴承箱{背景色:#e8e8e8;可见性:隐藏;字号:0;/*从0到100%设置动画*/不透明度:0;/*可选的*/转换:.5s;}#幻灯片放映{可见性:可见;字体大小:100%;/*从0到100%设置动画*/不透明度:1;/*可选的*/}#幻灯片隐藏*{边框顶部:0;边框底部:0;/*在这里放置任何以像素为单位的垂直线,在本例中为边框*/}a#按钮{显示:内联flex;对齐项目:居中;对齐内容:中心;位置:相对;宽度:20em;高度:3em;填充:0.5em;边框:2px实心#0080ff;边界半径:0.4em;背景色:#8fbfef;颜色:#404040;框大小调整:边框框;}#某种形式的{页边距:1em;边距底部:1em;填充:1 m 4 m 1 m 4 mm;背景色:#d8ffd8;边框:1px实心#888888;}#某种形式的输入{显示:内联块;框大小调整:边框框;字体大小:125%;填充:0.5em;宽度:50%;/*任何水平的都可以是px或%*/边界半径:0.4em;边框:1px纯红色;}<div id=page><a id=aclass href=“#”>开关类w/js</a><br>下面是滑动框:<div id=slidebox class=hide>我是幻灯片框的内容(第1行)<br>我是幻灯片框的内容(第2行)<br><a id=button href=“#”>我是幻灯片框中的某个按钮</a><br>我是幻灯片框的内容(第3行)<br>我是幻灯片框的内容(第4行)。<div id=someform>一个有表格的盒子<br><输入类型=文本值=“文本框”></div>我是幻灯片框的内容(第5行)<br>我是幻灯片框的内容(第6行)。</div>这是在盒子后面。</div>

其他回答

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

请参阅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>

Flexbox解决方案

赞成的意见:

易于理解的无JS平滑过渡

欺骗:

元素需要放在固定高度的柔性容器中

它的工作方式是始终具有灵活的基础:在元素上自动添加内容,并转换为灵活增长和灵活收缩。

编辑:受Xbox One界面启发,改进了JS Fiddle。

* {边距:0;填充:0;框大小调整:边框框;过渡:0.25s;字体系列:单空间;}正文{边距:10px 0 0 10px;}.box格式{宽度:150px;高度:150px;边距:0 2px 10px 0;背景:#2d333b;边框:实心10px#20262e;溢出:隐藏;显示:内联flex;弯曲方向:柱;}.空格{弹性基础:100%;挠曲生长:1;挠曲收缩:0;}p型{弹性基础:自动;柔性增长:0;挠曲收缩:1;背景:#20262e;填充:10px;宽度:100%;文本对齐:左侧;颜色:白色;}.box:悬停.space{柔性增长:0;挠曲收缩:1;}.box:悬停p{挠曲生长:1;挠曲收缩:0;}<div class=“box”><div class=“space”></div><p>超级Metroid Prime Fusion</p></div><div class=“box”><div class=“space”></div><p>《生化危机2》翻拍</p></div><div class=“box”><div class=“space”></div><p>Yolo游戏</p></div><div class=“box”><div class=“space”></div><p>《最终幻想7》重制版+所有附加DLC+金色礼帽</p></div><div class=“box”><div class=“space”></div><p>德普维尔</p></div>

JS小提琴

此解决方案使用了一些技术:

填充底部:100%“hack”,其中百分比是根据元素的当前宽度定义的。有关此技术的更多信息。浮动收缩包装,(需要额外的div来应用浮动清除黑客)非语义使用https://caniuse.com/#feat=css-编写模式和一些转换来撤销它(这允许在垂直上下文中使用上面的填充黑客)

结果是,我们只使用CSS实现了高性能的转换,并使用一个转换函数来平滑地实现转换;圣杯!

当然,这也有缺点!我无法确定如何控制内容被截断的宽度(溢出:隐藏);由于衬垫底部的裂缝,宽度和高度密切相关。不过,也许有办法,所以我们会回到过去。

https://jsfiddle.net/EoghanM/n1rp3zb4/28/

正文{填充:1em;}.触发器{字号:粗体;}/*.扩展器仅用于浮动清除*/.扩展器::之后{内容:“”;显示:表格;清晰:两者都有;}.外部{float:左;/*目的:收缩以适应内容*/边框:1px实心绿色;溢出:隐藏;}.内部{过渡:填充底部0.3s,方便进出;/*或者你能想出的任何疯狂的转换函数*/底部填充:0%;/*填充百分比是根据宽度定义的。此级别的宽度等于内容的高度*/高度:0;/*不幸的是,书写模式的改变还有其他的不良影响,比如光标的方向*/写入模式:垂直rl;光标:默认值;/*不需要垂直文本(横向工字梁)*/变换:旋转(-90度)平移X(-100%);/*撤消写入模式*/变换原点:0 0;边距:0;/*此处的左/右边距将增加高度*/}.inter>div{white-space:nowrap;}.extender:hover.intern,/*在展开时保持打开*/.t触发器:悬停+扩展器.内部{填充底部:100%;}<div class=“trigger”>HoverMe</div><div class=“扩展器”><div class=“outer”><div class=“inner”><div>第一项</div><div>内容</div><div>内容</div><div>内容</div><div>长内容不能宽于外部高度,不幸的是</div><div>最后一项</div></div></div></div><div>在内容之后</div></div>

我的解决方法是将最大高度转换为精确的内容高度,以获得流畅的动画效果,然后使用transitionEnd回调将最大高度设置为9999px,以便内容可以自由调整大小。

var content=$('#content');content.inner=$('#content.inter');//关闭时需要获取内容大小的内部div//css转换回调content.on('transitionEnd-webkitTransitionEnd transitiononend oTransitionEnd-msTransitionEnd',函数(e){if(content.hasClass('open')){content.css('max-height',9999);//尝试将此设置为“无”。。。我敢你!}});$('#toggle').on('click',函数(e){content.tggleClass(“打开关闭”);content.contentHeight=content.outerHeight();if(content.hasClass('closed')){//禁用转换&将最大高度设置为内容高度content.removeClass('transitions').css('max-height',content.contentHeight);setTimeout(函数){//启用和启动转换content.addClass('转换').css({'最大高度':0,“不透明度”:0});}, 10); // 10ms超时是禁用/启用转换的秘密因素//chrome只需要1ms,但FF需要约10ms,否则会在第一部动画中因某种原因而窒息}否则如果(content.hasClass('open')){content.contentHeight+=content.inter.outerHeight();//如果已关闭,请将内部高度添加到内容高度内容.css({'max height':content.contentHeight,“不透明度”:1});}});.转换{过渡:所有0.5秒都是缓进缓出;-webkit转换:所有0.5s都易于输入输出;-moz转换:所有0.5s都易于输入输出;}正文{字体系列:Arial;线高:3ex;}代码{显示:内联块;背景:#fafafa;填充:0 1ex;}#切换{显示:块;填充:10px;边距:10px自动;文本对齐:居中;宽度:30ex;}#内容{溢出:隐藏;边距:10px;边框:1px实心#666;背景:#efefef;不透明度:1;}#内容。内部{填充:10px;溢出:自动;}<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>在<code>height:0</code>和<code>high:auto</code>之间平滑CSS转换</h3><p>一个巧妙的解决方法是使用<code>max-height</code>而不是<code>height</code>,并将其设置为比内容更大的值。问题是浏览器使用此值来计算过渡持续时间。因此,如果您将其设置为<code>max-height:1000px</code>,但内容只有100px高,则动画将快10倍</p><p>另一种选择是使用JS测量内容高度,并转换到固定值,但如果内容发生变化,则必须跟踪内容并手动调整其大小</p><p>此解决方案是两种转换的混合,即转换到测量的内容高度,然后在转换后将其设置为<code>最大高度:9999px</code>,以调整流体内容大小</p></div></div><br/><button id=“toggle”>接受挑战</按钮>

杰克对最大高度动画化的回答很好,但我发现设置大的最大高度所导致的延迟很烦人。

可以将可折叠内容移动到内部div中,并通过获取内部div的高度来计算最大高度(通过JQuery,它将是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');
});

这里有一个jsfiddle链接:http://jsfiddle.net/pbatey/duZpT

这里有一个jsfiddle,它提供了所需的绝对最小代码量:http://jsfiddle.net/8ncjjxh8/