Chrome:网格容器以与内容不同的速率改变高度

问题描述 投票:0回答:1

下面是一个简化(且夸张)的手风琴示例,它使用网格来过渡内容的高度。

过渡有效,但在 Chrome 中表现得很奇怪:容器 (

.accordion
) 开始比内容增长得更快,并且内容需要一段时间才能赶上高度,因此在过渡期间,容器底部有一个间隙容器(见截图)。

在 Firefox 中,一切都按预期进行。

使用不同的转换函数(例如

linear
)仅影响容器的转换;差异依然存在。

这是 Chrome 中的一个错误吗?如果是,有解决方法吗?

height transition discrepancy in Chrome

.accordion {
    display: grid;
    grid-template-rows: minmax(0, 0fr) min-content;
    transition: grid-template-rows 3000ms;
    border: 1px solid;
    padding: 1rem;
}
    
.accordion.open {
    grid-template-rows: minmax(0, 1fr) min-content;
}
    
.content {
    overflow: hidden;
}
<div class="accordion">
    <div class="content">
        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam asperiores aut deserunt eaque incidunt labore laudantium minus nam omnis placeat quas quo, reprehenderit rerum soluta veritatis! Accusamus aliquam atque autem consequatur cumque, deserunt doloremque dolorum eaque eligendi esse est eum excepturi fugit hic impedit incidunt minus odit quae, ut voluptas.
        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam asperiores aut deserunt eaque incidunt labore laudantium minus nam omnis placeat quas quo, reprehenderit rerum soluta veritatis! Accusamus aliquam atque autem consequatur cumque, deserunt doloremque dolorum eaque eligendi esse est eum excepturi fugit hic impedit incidunt minus odit quae, ut voluptas.
        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam asperiores aut deserunt eaque incidunt labore laudantium minus nam omnis placeat quas quo, reprehenderit rerum soluta veritatis! Accusamus aliquam atque autem consequatur cumque, deserunt doloremque dolorum eaque eligendi esse est eum excepturi fugit hic impedit incidunt minus odit quae, ut voluptas.
    </div>
    <button onclick="this.parentElement.classList.toggle('open');">toggle</button>
</div>

css google-chrome css-grid css-transitions accordion
1个回答
0
投票

包裹并提取

当使用小于

grid-template-rows
的值并且具有多行时,我希望避免动画
1fr

使用新的 div 进行包装并从网格中提取按钮是一种可行的解决方案。

.accordion {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 3000ms;
  overflow: hidden; 
  align-items: flex-start;
  /* stretch is causing strange behavior, flex-start forces the element to have predictable height*/
}

.content {
  overflow: hidden;
}

.accordion.open {
  grid-template-rows: 1fr;
}

.wrapper {
  border: 1px solid;
  padding: 1rem;
}

button {
  width: 100%
}
<div class="wrapper">
  <div class="accordion">
    <div class="content">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam asperiores aut deserunt eaque incidunt labore laudantium minus nam omnis placeat quas quo, reprehenderit rerum soluta veritatis! Accusamus aliquam atque autem consequatur cumque, deserunt
      doloremque dolorum eaque eligendi esse est eum excepturi fugit hic impedit incidunt minus odit quae, ut voluptas. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam asperiores aut deserunt eaque incidunt labore laudantium minus nam
      omnis placeat quas quo, reprehenderit rerum soluta veritatis! Accusamus aliquam atque autem consequatur cumque, deserunt doloremque dolorum eaque eligendi esse est eum excepturi fugit hic impedit incidunt minus odit quae, ut voluptas. Lorem ipsum
      dolor sit amet, consectetur adipisicing elit. Aperiam asperiores aut deserunt eaque incidunt labore laudantium minus nam omnis placeat quas quo, reprehenderit rerum soluta veritatis! Accusamus aliquam atque autem consequatur cumque, deserunt doloremque
      dolorum eaque eligendi esse est eum excepturi fugit hic impedit incidunt minus odit quae, ut voluptas.
    </div>

  </div>
  <button onclick="this.parentElement.children[0].classList.toggle('open');">toggle</button>
</div>

其他解决方案也可能满足您的需求。您似乎正在实施一种将动画设置为

height: auto
的解决方法。还有其他具有不同权衡的解决方法。
IE
height: calc-size(auto);
登陆 chrome-canary,这应该会使从
height: 0
height: auto
的过渡变得更容易,但所有浏览器的采用肯定需要一些时间。

发生了什么事

Fr 单位:取可用空间的一小部分。

0fr
过渡到
1fr
。 我们将到达动画中间标记处的
0.5fr

此时,我们的 2 行网格行将是
0.5fr
+
min-content

网格总高度:内容高度+按钮高度=
100%

现在我们来到了症结所在(以及浏览器实现中的差异)。
0.5fr 或可用空间的 50% 是多少?总空间取决于子尺寸,子尺寸取决于总空间。

  • Firefox:似乎使用子尺寸(即
    100px
    ),并使其等于总尺寸=
    100px
  • Chrome:似乎使用子级大小(
    100px
    ),计算总数(
    100px
    ),然后再次将子级缩放到“可用空间”(
    0.5fr
    50px

谁是正确的? 我不知道,但 Firefox 对我来说更有意义。

  .accordion {
  width: 150px;
  display: grid;
  grid-template-rows: .5fr min-content;
  border: 1px solid;
  padding: 1rem;
  overflow: hidden;
}

.content {
  overflow: hidden;
}

.align-start {
  align-items: flex-start;
}

.example {
  margin: 50px;
  padding: 10px;
  background: linen;
<div class="example">Example: .5fr
  <div class="accordion">
    <div class="content">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam asperiores aut deserunt eaque incidunt labore laudantium minus nam omnis placeat quas quo, reprehenderit rerum soluta veritatis! Accusamus aliquam atque autem consequatur cumque, deserunt
      doloremque dolorum eaque eligendi esse est eum excepturi fugit hic impedit incidunt minus odit quae, ut voluptas.
    </div>
    <button onclick="this.parentElement.classList.toggle('open');">toggle</button>
  </div>
</div>

<div class="example">
  Example: .5fr with 'align-items: flex-start'
  <div class="accordion align-start">
    <div class="content">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam asperiores aut deserunt eaque incidunt labore laudantium minus nam omnis placeat quas quo, reprehenderit rerum soluta veritatis! Accusamus aliquam atque autem consequatur cumque, deserunt
      doloremque dolorum eaque eligendi esse est eum excepturi fugit hic impedit incidunt minus odit quae, ut voluptas.
    </div>
    <button onclick="this.parentElement.classList.toggle('open');">toggle</button>
  </div>
</div>


<div class="example">
  Example: .5fr with 'align-items: flex-start' moved button out of grid
  <div class="accordion align-start">
    <div class="content">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam asperiores aut deserunt eaque incidunt labore laudantium minus nam omnis placeat quas quo, reprehenderit rerum soluta veritatis! Accusamus aliquam atque autem consequatur cumque, deserunt
      doloremque dolorum eaque eligendi esse est eum excepturi fugit hic impedit incidunt minus odit quae, ut voluptas.
    </div>

  </div>
  <button onclick="this.parentElement.classList.toggle('open');">toggle</button>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.