【问题标题】:CSS transition auto height not working [duplicate]CSS过渡自动高度不起作用[重复]
【发布时间】:2012-12-05 23:35:54
【问题描述】:

我有一个网站,我决定用纯 CSS sn-ps 替换基于 jquery 的切换框。当我为过渡使用固定高度值(CSS的最后几行)时,效果很好,但是使用auto值时,动画丢失了,只有高度变化有效果!

有没有办法将它与自动值一起使用?我想使用可变文本而不是脚本。

.ac-container{
  width: 400px;
  margin: 10px auto 30px auto;
  text-align: left;
}
.ac-container label{
  font-family: 'BebasNeueRegular', 'Arial Narrow', Arial, sans-serif;
  padding: 5px 20px;
  position: relative;
  z-index: 20;
  display: block;
  height: 30px;
  cursor: pointer;
  color: #777;
  text-shadow: 1px 1px 1px rgba(255,255,255,0.8);
  line-height: 33px;
  font-size: 19px;
  background: #ffffff;
  background: -moz-linear-gradient(top, #ffffff 1%, #eaeaea 100%);
  background: -webkit-gradient(linear, left top, left bottom, color-stop(1%,#ffffff), color-stop(100%,#eaeaea));
  background: -webkit-linear-gradient(top, #ffffff 1%,#eaeaea 100%);
  background: -o-linear-gradient(top, #ffffff 1%,#eaeaea 100%);
  background: -ms-linear-gradient(top, #ffffff 1%,#eaeaea 100%);
  background: linear-gradient(top, #ffffff 1%,#eaeaea 100%);
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eaeaea',GradientType=0 );
  box-shadow: 
    0px 0px 0px 1px rgba(155,155,155,0.3), 
    1px 0px 0px 0px rgba(255,255,255,0.9) inset, 
    0px 2px 2px rgba(0,0,0,0.1);
}
.ac-container label:hover{
  background: #fff;
}
.ac-container input:checked + label,
.ac-container input:checked + label:hover{
  background: #c6e1ec;
  color: #3d7489;
  text-shadow: 0px 1px 1px rgba(255,255,255, 0.6);
  box-shadow: 
    0px 0px 0px 1px rgba(155,155,155,0.3), 
    0px 2px 2px rgba(0,0,0,0.1);
}

.ac-container input{
  display: none;
}
.ac-container section{
  background: rgba(255, 255, 255, 0.5);
  margin-top: -1px;
  overflow: hidden;
  height: 0px;
  position: relative;
  z-index: 10;
  -webkit-transition: height 0.3s ease-in-out, box-shadow 0.6s linear;
  -moz-transition: height 0.3s ease-in-out, box-shadow 0.6s linear;
  -o-transition: height 0.3s ease-in-out, box-shadow 0.6s linear;
  -ms-transition: height 0.3s ease-in-out, box-shadow 0.6s linear;
  transition: height 0.3s ease-in-out, box-shadow 0.6s linear;
}
.ac-container section p{
  font-style: italic;
  color: #777;
  line-height: 23px;
  font-size: 14px;
  padding: 20px;
  text-shadow: 1px 1px 1px rgba(255,255,255,0.8);
}
.ac-container input:checked ~ section{
  -webkit-transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
  -moz-transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
  -o-transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
  -ms-transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
  transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
  box-shadow: 0px 0px 0px 1px rgba(155,155,155,0.3);
}
.ac-container input:checked ~ section.ac-small{
  height: 120px; /*auto*/
}
<div class="ac-container">
  <div>

    <input id="ac-1" name="accordion-1" type="checkbox" />
    <section class="ac-small">
      <p>Some content... </p>
    </section>
    <label for="ac-1">About us</label>

  </div>	

  <div>	
    <input id="ac-2" name="accordion-2" type="checkbox" />
    <section class="ac-small">
      <p>Some content... </p>
    </section>
    <label for="ac-2">About us</label>
  </div>
</div>

【问题讨论】:

  • 如果不使用 javascript,我无法弄清楚自动高度/宽度属性上的 CSS 动画。

标签: css animation css-transitions


【解决方案1】:

CSS 过渡不适用于自动值。使用 JavaScript el.scrollHeight 获取滚动高度或使用 max-height 代替。

【讨论】:

  • 你的照片看起来更像是模特,而不是技术人员 +1
  • 也许你直接设置高度值而不是最大高度,那么它也可以。所以不需要这个半解决方法。
  • 如果一个值是auto 它也不起作用。与仅 CSS 问题相同。
【解决方案2】:

auto 不是动画属性的合适类型,请参阅CSS Transitions: 7. Animatable properties。您需要长度 (px,em,...) 或百分比 (13.37%)。

因此,只要不将auto 添加到列表中,就不可能使用纯 CSS 的解决方案。您需要使用 JavaScript 或特定的长度值。

【讨论】:

  • 如果我使用
    之类的部分周围的包装器并将 100% 作为部分高度怎么办?如何通过 div 访问该部分?
  • 没关系,它也有同样的效果:|
  • @Justme: ;)。工作草案对此非常清楚。只要auto 不是有效类型,您就需要使用某种解决方法。
【解决方案3】:

如果您只想使用 CSS,一个解决方案是转换 max-height 而不是 height 并将其设置为比以往任何时候都更大的值...

这是DEMO

您需要稍微调整一下转换的速度,但至少该示例让您了解如何完成。不要忘记在过渡中更改属性。从transition: height 0.5s;transition: max-height 0.5s;

希望这会有所帮助!

.ac-container{
    width: 400px;
    margin: 10px auto 30px auto;
    text-align: left;
}
.ac-container label{
    font-family: 'BebasNeueRegular', 'Arial Narrow', Arial, sans-serif;
    padding: 5px 20px;
    position: relative;
    z-index: 20;
    display: block;
    height: 30px;
    cursor: pointer;
    color: #777;
    text-shadow: 1px 1px 1px rgba(255,255,255,0.8);
    line-height: 33px;
    font-size: 19px;
    background: #ffffff;
    background: -moz-linear-gradient(top, #ffffff 1%, #eaeaea 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(1%,#ffffff), color-stop(100%,#eaeaea));
    background: -webkit-linear-gradient(top, #ffffff 1%,#eaeaea 100%);
    background: -o-linear-gradient(top, #ffffff 1%,#eaeaea 100%);
    background: -ms-linear-gradient(top, #ffffff 1%,#eaeaea 100%);
    background: linear-gradient(top, #ffffff 1%,#eaeaea 100%);
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eaeaea',GradientType=0 );
    box-shadow: 
        0px 0px 0px 1px rgba(155,155,155,0.3), 
        1px 0px 0px 0px rgba(255,255,255,0.9) inset, 
        0px 2px 2px rgba(0,0,0,0.1);
}
.ac-container label:hover{
    background: #fff;
}
.ac-container input:checked + label,
.ac-container input:checked + label:hover{
    background: #c6e1ec;
    color: #3d7489;
    text-shadow: 0px 1px 1px rgba(255,255,255, 0.6);
    box-shadow: 
        0px 0px 0px 1px rgba(155,155,155,0.3), 
        0px 2px 2px rgba(0,0,0,0.1);
}

.ac-container input{
    display: none;
}
.ac-container section{
    background: rgba(255, 255, 255, 0.5);
    margin-top: -1px;
    overflow: hidden;
    max-height: 0px;
    position: relative;
    z-index: 10;
    -webkit-transition: max-height 0.3s ease-in-out, box-shadow 0.6s linear;
    -moz-transition: max-height 0.3s ease-in-out, box-shadow 0.6s linear;
    -o-transition: max-height 0.3s ease-in-out, box-shadow 0.6s linear;
    -ms-transition: max-height 0.3s ease-in-out, box-shadow 0.6s linear;
    transition: max-height 0.3s ease-in-out, box-shadow 0.6s linear;
}
.ac-container section p{
    font-style: italic;
    color: #777;
    line-height: 23px;
    font-size: 14px;
    padding: 20px;
    text-shadow: 1px 1px 1px rgba(255,255,255,0.8);
}
.ac-container input:checked ~ section{
    -webkit-transition: max-height 0.5s ease-in-out, box-shadow 0.1s linear;
    -moz-transition: max-height 0.5s ease-in-out, box-shadow 0.1s linear;
    -o-transition: max-height 0.5s ease-in-out, box-shadow 0.1s linear;
    -ms-transition: max-height 0.5s ease-in-out, box-shadow 0.1s linear;
    transition: max-height 0.5s ease-in-out, box-shadow 0.1s linear;
    box-shadow: 0px 0px 0px 1px rgba(155,155,155,0.3);
}
.ac-container input:checked ~ section.ac-small{
    max-height: 500px; /*auto*/
}
<div class="ac-container">
    <div>
        
        <input id="ac-1" name="accordion-1" type="checkbox" />
        <section class="ac-small">
            <p>Some content...Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content... Some content...  </p>
        </section>
        <label for="ac-1">About us</label>
        
    </div>    

<div>    
        <input id="ac-2" name="accordion-2" type="checkbox" />
        <section class="ac-small">
            <p>Some content... </p>
        </section>
        <label for="ac-2">About us</label>
</div>
</div>

【讨论】:

  • 谢谢,这解决了我的问题!
  • 这是一个很棒的 DEMO。我只有一个问题:如果你选择一个更高的值(即 10000px)而不是 max-height:500px,动画会更快(当然更高的值和恒定的时间)。问题是,如果您不知道一个好的最大值是多少(因为截面高度可能要高得多)。所有部分都将不断快速动画化。需要一点 JavaScript 才能使实际部分变高并为其设置最大高度。这太烦人了,浏览器不会自己做。
  • 这仅适用于您打算在零和自动之间转换的场景,而不是自动和自动之间的转换(即当里面的内容发生变化时)
  • 先生……你真是个天才!!!努夫说。
  • 有史以来最糟糕的例子。如果给出的示例尽量减少主题,那将是很好的。那里有太多绒毛,我什至懒得去弄清楚那里是否有任何价值。
【解决方案4】:

您不能在“自动”维度进行动画处理(很遗憾)。我通常的方法是为具有单个子元素的外部 DIV 的高度设置动画,该子元素是无样式 DIV,仅用于测量内容高度。

function growDiv() {
  var growDiv = document.getElementById('grow');
  if (growDiv.clientHeight) {
    growDiv.style.height = 0;
  } else {
    var wrapper = document.querySelector('.measuringWrapper');
    growDiv.style.height = wrapper.clientHeight + "px";
  }
}
#grow {
  -moz-transition: height .5s;
  -ms-transition: height .5s;
  -o-transition: height .5s;
  -webkit-transition: height .5s;
  transition: height .5s;
  height: 0;
  overflow: hidden;
  outline: 1px solid red;
}
<input type="button" onclick="growDiv()" value="grow">
<div id='grow'>
  <div class='measuringWrapper'>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
  </div>
</div>

【讨论】:

  • 我更喜欢这个而不是接受的答案。我认为您甚至不需要 measuringWrapper 类。我用这样的东西来检测要设置的高度:Array.from(growDiv.children).map(el =&gt; el.clientHeight).reduce((a, b) =&gt; a + b, 0)
  • 这个实际上是动画高度。谢谢。
【解决方案5】:

你应该使用 scaleY。

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

或者您可以使用clip剪切列表。

ul {
  clip: rect(auto, auto, 0, auto);
  position: absolute;
  margin: 0;
  padding: .5rem;

  color: white;

  background-color: rgba(0, 0, 0, 0.8);

  transition-delay: 0.29s;
  transition-property: clip;
  transition-duration: 0.5s;
  transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
h3:hover ~ ul,
h3:active ~ ul {
  clip: rect(auto, auto, 10rem, auto);
}
<h3>Hover here</h3>
<ul>
  <li>This list</li>
  <li>is clipped.</li>
  <li>A clip transition</li>
  <li>will show it</li>
</ul>
<p>
  Some text...
</p>

【讨论】:

  • 这不起作用,因为当对象为 scaleY(0) 时,DOM 中仍保留完整高度
  • 伟大的!这有助于我与上面的 max-height 进行混合,以便消失的元素(缩放到 0)不使用空间,并避免转换顺序的 max-height 问题(这使得具有实际目标的元素在新目标出现后消失,将目标内容从它应该在的位置移动)。可以在此处查看包含 translateY(MaxH、MaxH+TranslateY 和 MaxH+Scale)的额外选项的示例(使用选中,而不是目标)codepen.io/davidtaubmann/pen/zKZvGP
  • 剪辑已弃用
  • 但它永远不会被淘汰。 clipCSS Masking Module 中被弃用,取而代之的是剪辑路径,但 clip 我们知道它永远不会消失。 “在本规范中,不推荐使用 clip 属性。鼓励作者使用 clip-path 属性。UA 必须支持 clip 属性。”
  • 使用比例而不是最大高度对性能有好处。感谢 dotnetCarpenter。如果你阅读了关于渲染的 google 性能手册,你会发现添加 will-change CSS 设置是很好的。 developers.google.com/web/fundamentals/design-and-ux/animations/…
猜你喜欢
相关资源
最近更新 更多
热门标签