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


当前回答

当我发布这篇文章时,已经有30多个答案了,但我觉得我的答案比杰克已经接受的答案要好。

我对简单地使用最大高度和CSS3转换产生的问题并不满意,因为正如许多评论人士所指出的,你必须将最大高度值设置得非常接近实际高度,否则会延迟。有关该问题的示例,请参阅此JSFiddle。

为了解决这个问题(虽然仍然不使用JavaScript),我添加了另一个转换转换的HTML元素:translateY CSS值。

这意味着同时使用了max-height和translateY:max-heith允许元素向下推它下面的元素,而translateY提供了我们想要的“即时”效果。最大高度的问题仍然存在,但其影响有所减弱。这意味着你可以为你的最大高度值设置一个更大的高度,而不用担心它。

总的好处是,在转换回(塌陷)时,用户可以立即看到translateY动画,因此最大高度需要多长时间并不重要。

解决方案为Fiddle

正文{字体系列:无衬线;}.切换{位置:相对;边框:2px实心#333;边界半径:3px;边距:5px;宽度:200px;}.切换标题{边距:0;填充:10px;背景色:#333;颜色:白色;文本对齐:居中;光标:指针;}.拨动高度{背景色:番茄;溢出:隐藏;过渡:最大高度。6s轻松;最大高度:0;}.tggle:悬停.tggle高度{最大高度:1000px;}.tggle转换{填充:5px;颜色:白色;转换:转换。4s轻松;变换:translateY(-100%);}.tggle:悬停.tggle变换{变换:translateY(0);}<div class=“toggle”><div class=“toggle header”>切换!</div><div class=“toggle height”><div class=“toggle transform”><p>内容</p><p>内容</p><p>内容</p><p>内容</p></div></div></div><div class=“toggle”><div class=“toggle header”>切换!</div><div class=“toggle height”><div class=“toggle transform”><p>内容</p><p>内容</p><p>内容</p><p>内容</p></div></div></div>

其他回答

你可以,用一点非语义的小把戏。我通常的方法是设置外部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>

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

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小提琴

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

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

我使用的方法是基于字体大小(使用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>

扩展@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/