下面是一个简化(且夸张)的手风琴示例,它使用网格来过渡内容的高度。
过渡有效,但在 Chrome 中表现得很奇怪:容器 (
.accordion
) 开始比内容增长得更快,并且内容需要一段时间才能赶上高度,因此在过渡期间,容器底部有一个间隙容器(见截图)。
在 Firefox 中,一切都按预期进行。
使用不同的转换函数(例如
linear
)仅影响容器的转换;差异依然存在。
这是 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>
当使用小于
grid-template-rows
的值并且具有多行时,我希望避免动画 1fr
。.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
的解决方法。还有其他具有不同权衡的解决方法。height: calc-size(auto);
登陆 chrome-canary,这应该会使从 height: 0
到 height: auto
的过渡变得更容易,但所有浏览器的采用肯定需要一些时间。
Fr 单位:取可用空间的一小部分。
从
0fr
过渡到1fr
。 我们将到达动画中间标记处的 0.5fr
。0.5fr
+ min-content
。100%
现在我们来到了症结所在(以及浏览器实现中的差异)。
0.5fr 或可用空间的 50% 是多少?总空间取决于子尺寸,子尺寸取决于总空间。
100px
),并使其等于总尺寸=100px
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>