如何转换高度:0; 达到高度:自动;使用CSS?

我正在尝试<ul>使用CSS过渡制作幻灯片。

<ul>在开始关闭height: 0;悬停时,高度设置为height:auto;但是,这导致它只是显示而不是过渡,

如果我从height: 40px;到进行操作height: auto;,则它将滑到height: 0;,然后突然跳到正确的高度。

不使用JavaScript,我还能怎么做?

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

Tony达蒙2020/03/13 15:57:28

我没有详细阅读所有内容,但是最近遇到了这个问题,我做了以下工作:

div.class{
   min-height:1%;
   max-height:200px;
   -webkit-transition: all 0.5s ease;
   -moz-transition: all 0.5s ease;
   -o-transition: all 0.5s ease;
   -webkit-transition: all 0.5s ease;
   transition: all 0.5s ease;
   overflow:hidden;
}

div.class:hover{
   min-height:100%;
   max-height:3000px;
}

这样一来,您可以创建一个div,该div首先显示最高200像素的高度,然后将其悬停,其大小至少应与div的整个内容一样高。Div不会变为3000px,但我要施加的极限是3000px。确保在non:hover上进行过渡,否则可能会得到一些奇怪的渲染。这样,:hover将从非:hover继承。

从px到%或自动的过渡均无效。您需要使用相同的度量单位。这对我来说很好。使用HTML5使其完美。

请记住,总有解决方法……;

希望有人觉得这有用

EvaGO樱2020/03/13 15:57:28

这并不是解决问题的“解决方案”,而是更多的解决方法。我确定它只能与文本一起使用,但是可以根据需要更改为与其他元素一起使用。

.originalContent {
    font-size:0px;
    transition:font-size .2s ease-in-out;
}
.show { /* class to add to content */
    font-size:14px;
}

这是一个示例:http : //codepen.io/overthemike/pen/wzjRKa

本质上,您将font-size设置为0并以足够快的速度转换它,而不是转换高度,max-height或scaleY()等,以使高度转换为所需的高度。当前无法使用CSS将实际高度转换为自动,但是可以转换其中的内容,因此可以转换字体大小。

  • 注意-Codepen中有JavaScript,但唯一的目的是单击时添加/删除CSS类的手风琴。这可以通过隐藏的单选按钮完成,但是我并没有专注于此,只是高度转换。
村村樱2020/03/13 15:57:28

如果提供的硬编码最大高度值不大于实际高度,则杰克(Jake)的最大高度解决方案可以很好地工作(因为否则会有不希望的延迟和计时问题)。另一方面,如果硬编码值偶然不大于实际高度,则该元素将不会完全打开。

以下仅CSS解决方案还需要硬编码的大小,该大小应大于大多数实际大小。但是,如果实际大小在某些情况下大于硬编码大小,则此解决方案也适用。在那种情况下,过渡可能会跳一点,但绝不会留下部分可见的元素。因此,该解决方案还可以用于未知内容,例如来自数据库的未知内容,您只知道其中的内容通常不大于x像素,但是也有例外。

想法是对底边距使用负值(对于稍有不同的动画,对边距顶部使用负值),然后将内容元素放入带有overflow:hidden的中间元素中。内容元素的负边距会降低中间元素的高度。

下面的代码使用从-150px到0px的margin-bottom过渡。只要content元素不高于150px,这单独就可以正常工作。另外,它对中间元素的最大高度使用了从0px到100%的过渡。如果content元素高于150px,则最终将隐藏中间元素。对于最大高度,过渡仅用于在关闭时将其应用延迟一秒,而不是获得平滑的视觉效果(因此过渡范围可以从0px到100%)。

CSS:

.content {
  transition: margin-bottom 1s ease-in;
  margin-bottom: -150px;
}
.outer:hover .middle .content {
  transition: margin-bottom 1s ease-out;
  margin-bottom: 0px
}
.middle {
  overflow: hidden;
  transition: max-height .1s ease 1s;
  max-height: 0px
}
.outer:hover .middle {
  transition: max-height .1s ease 0s;
  max-height: 100%
}

HTML:

<div class="outer">
  <div class="middle">
    <div class="content">
      Sample Text
      <br> Sample Text
      <br> Sample Text
      <div style="height:150px">Sample Test of height 150px</div>
      Sample Text
    </div>
  </div>
  Hover Here
</div>

边距下限值应为负,并尽可能接近内容元素的实际高度。如果它的(绝对值)较大,则存在与最大高度解决方案类似的延迟和时序问题,但是,只要硬编码的大小不比实际大小大很多,就可以限制它们。如果边缘下限的绝对值小于实际高度,则过渡会略微跳跃。在过渡之后的任何情况下,内容元素都将完全显示或完全删除。

有关更多详细信息,请参阅我的博客文章http://www.taccgl.org/blog/css_transition_display.html#combined_height

Harry前端Itachi2020/03/13 15:57:28

我想我想出了一个非常可靠的解决方案

好!我知道这个问题与互联网一样古老,但是我想我有一个解决方案,后来我将其变成了名为mutant-transition插件style=""每当DOM发生变化时,我的解决方案都会为跟踪元素设置属性。最终结果是,您可以在转换中使用优质的ole CSS,而无需使用hacky修复程序或特殊的javascript。您唯一要做的就是使用来设置要在相关元素上跟踪的内容data-mutant-attributes="X"

<div data-mutant-attributes="height">                                                                      
        This is an example with mutant-transition                                                                                                          
    </div>

而已!该解决方案使用MutationObserver来跟踪DOM中的更改。因此,您实际上无需设置任何内容或使用javascript手动设置事物的动画。更改会自动跟踪。但是,由于它使用MutationObserver,因此只能在IE11 +中转换。

小提琴!

猴子JinJin2020/03/13 15:57:28

我最近一直在转变max-heightli元素,而不是包装ul

其理由是,对于小的延迟max-heights远没有那么明显(如果有的话)相比大max-heights了,我也可以在我的设置max-height相对价值font-sizeli,而不是一些任意数量庞大的使用emsrems

如果我的字体大小为1rem,则将其设置max-height3rem(容纳换行文本)。您可以在此处查看示例:

http://codepen.io/mindfullsilence/pen/DtzjE

逆天乐2020/03/13 15:57:27

我已经使用以下文章的技术2:transform:scaleY()满足了没有JS的要求。

https://css-tricks.com/using-css-transitions-auto-dimensions/

.wrapper ul {
  transform: scaleY(0);
  transform-origin: top;
  transition: 0.3s;
  height: 0;
}

.wrapper:hover ul {
  height: auto;
  transform: scaleY(1)
}
<div class="wrapper">
  <h2>List</h2>
  <ul>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
  </ul>
</div>

GO西里2020/03/13 15:57:27

几乎没有提及该Element.scrollHeight属性,属性在这里可能有用,但仍然可以与纯CSS过渡一起使用。该属性始终包含元素的“完整”高度,无论其内容是否由于高度折叠(例如height: 0而溢出以及如何溢出

这样,对于height: 0(有效完全折叠)的元素,其“正常”或“完整”高度仍可通过其scrollHeight值(不变地为像素长度)轻松获得

对于这样的元素,假设它已经设置了转换,例如(ul按照原始问题使用):

ul {
    height: 0;
    transition: height 1s; /* An example transition. */
}

我们可以仅使用CSS触发所需的动画高度“扩展”,如下所示(此处假设ul变量是指列表):

ul.style.height = ul.scrollHeight + "px";

而已。如果您需要折叠列表,则可以使用以下两个语句之一:

ul.style.height = "0";
ul.style.removeProperty("height");

我的特定用例围绕着动画列表,这些列表的长度未知且通常很长,因此我不适应使用任意的“足够大” heightmax-height规范,并冒着截断的内容或突然需要滚动的内容的风险(overflow: auto例如,如果) 。此外,max-height基于解决方案的宽松程度和时机被打破,因为使用的高度可能比达到高度max-height要快得多9999px随着屏幕分辨率的提高,象素的长度会9999px在我的嘴里留下不良的味道。我认为,这种特殊的解决方案以一种优雅的方式解决了这个问题。

最后,这里希望CSS的未来修订版能够满足作者的要求,使他们更加优雅地做这些事情-重新审视“ compute” vs“ used”和“ resolved”值的概念,并考虑是否应将过渡应用于计算值。值,包括使用width转换height(目前有一些特殊处理)。

达蒙猪猪2020/03/13 15:57:27

Flexbox解决方案

优点:

  • 简单
  • 没有JS
  • 平稳过渡

缺点:

  • 元素需要放在固定高度的flex容器中

它的工作方式是始终具有flex-basis:在具有内容的元素上自动放置,然后过渡flex-grow和flex-shrink。

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

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  transition: 0.25s;
  font-family: monospace;
}

body {
  margin: 10px 0 0 10px;
}

.box {
  width: 150px;
  height: 150px;
  margin: 0 2px 10px 0;
  background: #2d333b;
  border: solid 10px #20262e;
  overflow: hidden;
  display: inline-flex;
  flex-direction: column;
}

.space {
  flex-basis: 100%;
  flex-grow: 1;
  flex-shrink: 0;    
}

p {
  flex-basis: auto;
  flex-grow: 0;
  flex-shrink: 1;
  background: #20262e;
  padding: 10px;
  width: 100%;
  text-align: left;
  color: white;
}

.box:hover .space {
  flex-grow: 0;
  flex-shrink: 1;
}
  
.box:hover p {
  flex-grow: 1;
  flex-shrink: 0;    
}
<div class="box">
  <div class="space"></div>
  <p>
    Super Metroid Prime Fusion
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    Resident Evil 2 Remake
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    Yolo The Game
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    Final Fantasy 7 Remake + All Additional DLC + Golden Tophat
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    DerpVille
  </p>
</div>

JS小提琴

StafanJim2020/03/13 15:57:27

使用CSS3过渡为高度设置动画的可视化解决方法是对填充进行动画处理。

您还不能完全获得擦除效果,但是使用过渡时间和填充值应该可以使您足够接近。如果您不想显式设置height / 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上方摘下来)

理查德西门Near2020/03/13 15:57:27

您可以从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;
}
HarryStafan2020/03/13 15:57:27

编辑:向下滚动以获取更新的答案,
我正在制作一个下拉列表,并看到了此帖子...许多不同的答案,但我决定也分享我的下拉列表,...这并不完美,但至少它将仅使用CSS作为落下!我一直在使用transform:translateY(y)将列表转换为视图...
您可以在测试中看到更多信息
http://jsfiddle.net/BVEpc/4/
我将div放在每个li后面是因为下拉列表是从上而来的,为了正确显示它们是必需的,我的div代码是:

#menu div {
    transition: 0.5s 1s;
    z-index:-1;
    -webkit-transform:translateY(-100%);
    -webkit-transform-origin: top;
}

悬停是:

#menu > li:hover div {
    transition: 0.5s;
    -webkit-transform:translateY(0);
}

并且因为ul height设置为内容,所以它可以覆盖您的身体内容,这就是我为ul执行此操作的原因:

 #menu ul {
    transition: 0s 1.5s;
    visibility:hidden;
    overflow:hidden;
}

并悬停:

#menu > li:hover ul {
     transition:none;
     visibility:visible;
}

过渡之后的第二次是延迟,在我的下拉列表被动画关闭后,它将隐藏起来。
希望以后有人从中受益。

编辑:我简直不敢相信ppl实际上使用了这个原型!该下拉菜单仅适用于一个子菜单,仅此而已!我更新了一个更好的版本,可以在支持IE 8的同时为ltr和rtl方向提供两个子菜单。
LTR的
Fiddle的RTL的Fiddle的
希望,以后有人会觉得有用。

Tony米亚2020/03/13 15:57:27

好的,我想我想出了一个非常简单的答案...不max-height,使用relative定位,在li元素上工作,并且是纯CSS。除了Firefox之外,我没有在其他任何软件上进行过测试,尽管从CSS来看,它应该可以在所有浏览器上使用。

内容:http : //jsfiddle.net/n5XfG/2596/

的CSS

.wrap { overflow:hidden; }

.inner {
            margin-top:-100%;
    -webkit-transition:margin-top 500ms;
            transition:margin-top 500ms;
}

.inner.open { margin-top:0px; }

的HTML

<div class="wrap">
    <div class="inner">Some Cool Content</div>
</div>
小次郎2020/03/13 15:57:27

max-height针对每个状态使用不同的过渡缓和和延迟。

HTML:

<a href="#" id="trigger">Hover</a>
<ul id="toggled">
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
<ul>

CSS:

#toggled{
    max-height: 0px;
    transition: max-height .8s cubic-bezier(0, 1, 0, 1) -.1s;
}

#trigger:hover + #toggled{
    max-height: 9999px;
    transition-timing-function: cubic-bezier(0.5, 0, 1, 0); 
    transition-delay: 0s;
}

参见示例:http : //jsfiddle.net/0hnjehjc/1/

伽罗Mandy2020/03/13 15:57:27

我一直使用的解决方案是第一个淡出,然后收缩font-sizepaddingmargin值。它看起来与抹布并不相同,但无需使用height或即可使用max-height

工作示例:

/* final display */
#menu #list {
    margin: .5em 1em;
    padding: 1em;
}

/* hide */
#menu:not(:hover) #list {
    font-size: 0;
    margin: 0;
    opacity: 0;
    padding: 0;
    /* fade out, then shrink */
    transition: opacity .25s,
                font-size .5s .25s,
                margin .5s .25s,
                padding .5s .25s;
}

/* reveal */
#menu:hover #list {
    /* unshrink, then fade in */
    transition: font-size .25s,
                margin .25s,
                padding .25s,
                opacity .5s .25s;
}
<div id="menu">
    <b>hover me</b>
    <ul id="list">
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
</div>

<p>Another paragraph...</p>

GOL蛋蛋2020/03/13 15:57:26

您应该改用scaleY。

ul {
  background-color: #eee;
  transform: scaleY(0);    
  transform-origin: top;
  transition: transform 0.26s ease;
}
p:hover ~ ul {
  transform: scaleY(1);
}
<p>Hover This</p>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

我做了上述代码的供应商前缀版本的jsfiddle,并改变了你的jsfiddle到使用的scaleY,而不是高度。

LGO西里2020/03/13 15:57:26

当涉及的高度之一是时auto,您当前无法在高度上设置动画,您必须设置两个显式的高度。